changeset 211:8980dc2deda0

emacs: use package.el to bootstrap instead of checking in all needed libs
author Augie Fackler <durin42@gmail.com>
date Sat, 13 Feb 2010 20:00:15 -0600
parents 0590f34b92a0
children 4716b238db2e
files .elisp/diff-mode-.el .elisp/doctest-mode.el .elisp/http-twiddle.el .elisp/ipython.el .elisp/js2.el .elisp/js2.elc .elisp/nose.el .elisp/package.el .elisp/paredit.el .elisp/pycomplete.el .elisp/pycomplete.py .elisp/pymacs.el .elisp/settings/10.require.el .elisp/yaml-mode.el
diffstat 14 files changed, 1472 insertions(+), 17790 deletions(-) [+]
line wrap: on
line diff
deleted file mode 100644
--- a/.elisp/diff-mode-.el
+++ /dev/null
@@ -1,189 +0,0 @@
-;;; diff-mode-.el --- Extensions to `diff-mode.el'.
-;;
-;; Filename: diff-mode-.el
-;; Description: Extensions to `diff-mode.el'.
-;; Author: Drew Adams
-;; Maintainer: Drew Adams
-;; Copyright (C) 2004-2009, Drew Adams, all rights reserved.
-;; Created: Mon Nov 08 16:36:09 2004
-;; Version: 21.0
-;; Last-Updated: Sat Dec 27 10:19:33 2008 (-0800)
-;;           By: dradams
-;;     Update #: 646
-;; URL: http://www.emacswiki.org/cgi-bin/wiki/diff-mode-.el
-;; Keywords: data, matching, tools, unix, local, font, face
-;; Compatibility: GNU Emacs 21.x, GNU Emacs 22.x
-;;
-;; Features that might be required by this library:
-;;
-;;   None
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Commentary:
-;;
-;;    Extensions to `diff-mode.el'.
-;;
-;;  "*Diff*" buffer is highlighted differently.
-;;
-;;  NOTE: The faces defined here look best on a medium-dark
-;;        background, because some are light and some are dark.
-;;        Try, for example, setting the background to "LightSteelBlue"
-;;        in your `~/.emacs' file: You can do this is via
-;;        `special-display-buffer-names':
-;;
-;;         (setq special-display-buffer-names
-;;               (cons '("*Diff*" (background-color . "LightSteelBlue"))
-;;                     special-display-buffer-names))
-;;
-;;        You can alternatively change the background value of
-;;        `special-display-frame-alist' and set
-;;        `special-display-regexps' to something matching "*info*":
-;;
-;;         (setq special-display-frame-alist
-;;               (cons '(background-color . "LightSteelBlue")
-;;                     special-display-frame-alist))
-;;         (setq special-display-regexps '("[ ]?[*][^*]+[*]"))
-;;
-;;
-;;  New faces defined here:
-;;
-;;    `diff-file1-hunk-header', `diff-file2-hunk-header'.
-;;
-;;  New user options defined here:
-;;
-;;    `diff-file1-hunk-header-face', `diff-file2-hunk-header-face'.
-;;
-;;
-;;  ***** NOTE: The following faces defined in `diff-mode.el' have
-;;              been REDEFINED HERE:
-;;
-;;    `diff-added', `diff-changed', `diff-context',
-;;    `diff-file-header', `diff-header', `diff-hunk-header',
-;;    `diff-index', `diff-indicator-added', `diff-indicator-changed',
-;;    `diff-indicator-removed', `diff-nonexistent', `diff-removed'.
-;;
-;;
-;;  ***** NOTE: The following variable defined in `diff-mode.el' has
-;;              been REDEFINED HERE:
-;;
-;;    `diff-font-lock-keywords'.
-;;
-;;
-;;  This library should be loaded *before* library `diff-mode.el'.
-;;  Put this in your initialization file, `~/.emacs':
-;;    (require 'diff-mode-)
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Change log:
-;;
-;; 2008/01/01 dadams
-;;     Added :group for deffaces.
-;; 2006/01/04 dadams
-;;     Updated to use new Emacs 22 face names for indicator faces.
-;;       Thanks to Juri Linkov for the letting me know about the new faces.
-;;     Updated diff-font-lock-keywords to be = Emacs 22, except for file name.
-;; 2006/01/01 dadams
-;;     Renamed faces, without "-face".
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
-;; Floor, Boston, MA 02110-1301, USA.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Code:
-
-;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-;;; Define some additional faces.
-(defface diff-file1-hunk-header
-  '((t (:foreground "Blue" :background "DarkSeaGreen1")))
-  "Face used to highlight a diff hunk for the first `diff' argument."
-  :group 'diff-mode)
-(defvar diff-file1-hunk-header-face 'diff-file1-hunk-header)
-
-(defface diff-file2-hunk-header
-  '((t (:foreground "Red" :background "PaleGoldenrod")))
-  "Face used to highlight a diff hunk for the second `diff' argument."
-  :group 'diff-mode)
-(defvar diff-file2-hunk-header-face 'diff-file2-hunk-header)
-
-;;; These faces are standard in Emacs 22, but they are new for Emacs 21.
-(defface diff-indicator-changed
-  '((t (:foreground "PaleGoldenrod" :background "MediumBlue")))
-  "*Face used to highlight the line-start indicator of a modified line."
-  :group 'diff-mode)
-(defvar diff-indicator-changed-face 'diff-indicator-changed)
-
-(defface diff-indicator-added
-  '((t (:foreground "PaleGoldenrod" :background "DarkGreen")))
-  "*Face used to highlight the line-start indicator of an inserted line."
-  :group 'diff-mode)
-(defvar diff-indicator-added-face 'diff-indicator-added)
-
-(defface diff-indicator-removed
-  '((t (:foreground "PaleGoldenrod" :background "DarkMagenta")))
-  "*Face used to highlight the line-start indicator of a removed line."
-  :group 'diff-mode)
-(defvar diff-indicator-removed-face 'diff-indicator-removed)
-
-;;; Change existing `diff-mode' faces too.
-(custom-set-faces
- '(diff-added ((t (:foreground "DarkGreen"))) 'now)
- '(diff-changed ((t (:foreground "MediumBlue"))) 'now)
- '(diff-context ((t (:foreground "LightSteelBlue"))) 'now)
- '(diff-file-header ((t (:foreground "White"))) 'now)
- '(diff-header ((t (:foreground "White"))) 'now)
- '(diff-hunk-header ((t (:foreground "White"))) 'now)
- '(diff-index ((t (:foreground "Green"))) 'now)
- '(diff-nonexistent ((t (:foreground "DarkBlue"))) 'now)
- '(diff-removed ((t (:foreground "Red"))) 'now)
- )
-
-;;; The only real difference here now from the standard Emacs 22 version is the
-;;; use of diff-file1* and diff-file2*.
-(defvar diff-font-lock-keywords
-  `(
-    ("^\\(@@ -[0-9,]+ \\+[0-9,]+ @@\\)\\(.*\\)$" ;unified
-     (1 diff-hunk-header-face) (2 diff-function-face))
-    ("^\\(\\*\\{15\\}\\)\\(.*\\)$"      ;context
-     (1 diff-hunk-header-face) (2 diff-function-face))
-    ("^\\*\\*\\* .+ \\*\\*\\*\\*". diff-file1-hunk-header-face) ;context
-    ("^--- .+ ----$" . diff-file2-hunk-header-face) ;context
-    ("^[0-9,]+[acd][0-9,]+$" . diff-hunk-header-face) ; normal
-    ("^---$" . diff-hunk-header-face)   ;normal
-    ("^\\(---\\|\\+\\+\\+\\|\\*\\*\\*\\) \\(\\S-+\\)\\(.*[^*-]\\)?\n"
-     (0 diff-header-face) (2 diff-file-header-face prepend))
-    ("^\\([-<]\\)\\(.*\n\\)" (1 diff-indicator-removed-face) (2 diff-removed-face))
-    ("^\\([+>]\\)\\(.*\n\\)" (1 diff-indicator-added-face) (2 diff-added-face))
-    ("^\\(!\\)\\(.*\n\\)" (1 diff-indicator-changed-face) (2 diff-changed-face))
-    ("^Index: \\(.+\\).*\n" (0 diff-header-face) (1 diff-index-face prepend))
-    ("^Only in .*\n" . diff-nonexistent-face)
-    ("^\\(#\\)\\(.*\\)"
-     (1 (if (facep 'font-lock-comment-delimiter-face)
-            'font-lock-comment-face))
-     (2 font-lock-comment-face))
-    ("^[^-=+*!<>#].*\n" (0 diff-context-face))))
-
-;;;;;;;;;;;;;;;;;;;;;;;
-
-(provide 'diff-mode-)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; diff-mode-.el ends here
deleted file mode 100644
--- a/.elisp/doctest-mode.el
+++ /dev/null
@@ -1,2061 +0,0 @@
-;;; doctest-mode.el --- Major mode for editing Python doctest files
-
-;; Copyright (C) 2004-2007  Edward Loper
-
-;; Author:     Edward Loper
-;; Maintainer: edloper@alum.mit.edu
-;; Created:    Aug 2004
-;; Keywords:   python doctest unittest test docstring
-
-(defconst doctest-version "0.5 alpha"
-  "`doctest-mode' version number.")
-
-;; This software is provided as-is, without express or implied
-;; warranty.  Permission to use, copy, modify, distribute or sell this
-;; software, without fee, for any purpose and by any individual or
-;; organization, is hereby granted, provided that the above copyright
-;; notice and this paragraph appear in all copies.
-
-;; This is a major mode for editing text files that contain Python
-;; doctest examples.  Doctest is a testing framework for Python that
-;; emulates an interactive session, and checks the result of each
-;; command.  For more information, see the Python library reference:
-;; <http://docs.python.org/lib/module-doctest.html>
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Table of Contents
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;  1. Customization: use-editable variables to customize
-;;     doctest-mode.
-;;
-;;  2. Fonts: defines new font-lock faces.
-;;
-;;  3. Constants: various consts (mainly regexps) used by the rest
-;;     of the code.
-;;
-;;  4. Syntax Highlighting: defines variables and functions used by
-;;     font-lock-mode to perform syntax highlighting.
-;;
-;;  5. Source code editing & indentation: commands used to
-;;     automatically indent, dedent, & handle prompts.
-;;
-;;  6. Code Execution: commands used to start doctest processes,
-;;     and handle their output.
-;;
-;;  7. Markers: functions used to insert markers at the start of
-;;     doctest examples.  These are used to keep track of the
-;;     correspondence between examples in the source buffer and
-;;     results in the output buffer.
-;;
-;;  8. Navigation: commands used to navigate between failed examples.
-;;
-;;  9. Replace Output: command used to replace a doctest example's
-;;     expected output with its actual output.
-;;
-;; 10. Helper functions: various helper functions used by the rest
-;;     of the code.
-;;
-;; 11. Emacs compatibility functions: defines compatible versions of
-;;     functions that are defined for some versions of emacs but not
-;;     others.
-;;
-;; 12. Doctest Results Mode: defines doctest-results-mode, which is
-;;     used for the output generated by doctest.
-;;
-;; 13. Doctest Mode: defines doctest-mode itself.
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Customizable Constants
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defgroup doctest nil
-  "Support for the Python doctest framework"
-  :group 'languages
-  :prefix "doctest-")
-
-(defcustom doctest-default-margin 4
-  "The default pre-prompt margin for doctest examples."
-  :type 'integer
-  :group 'doctest)
-
-(defcustom doctest-avoid-trailing-whitespace t
-  "If true, then delete trailing whitespace when inserting a newline."
-  :type 'boolean
-  :group 'doctest)
-
-(defcustom doctest-temp-directory
-  (let ((ok '(lambda (x)
-	       (and x
-		    (setq x (expand-file-name x)) ; always true
-		    (file-directory-p x)
-		    (file-writable-p x)
-		    x))))
-    (or (funcall ok (getenv "TMPDIR"))
-	(funcall ok "/usr/tmp")
-	(funcall ok "/tmp")
-	(funcall ok "/var/tmp")
-	(funcall ok  ".")
-	(error (concat "Couldn't find a usable temp directory -- "
-		       "set `doctest-temp-directory'"))))	 
-  "Directory used for temporary files created when running doctest.
-By default, the first directory from this list that exists and that you
-can write into: the value (if any) of the environment variable TMPDIR,
-/usr/tmp, /tmp, /var/tmp, or the current directory."
-  :type 'string
-  :group 'doctest)
-
-(defcustom doctest-hide-example-source nil
-  "If true, then don't display the example source code for each 
-failure in the results buffer."
-  :type 'boolean
-  :group 'doctest)
-
-(defcustom doctest-python-command "python"
-  "Shell command used to start the python interpreter"
-  :type 'string
-  :group 'doctest)
-
-(defcustom doctest-results-buffer-name "*doctest-output (%N)*"
-  "The name of the buffer used to store the output of the doctest
-command.  This name can contain the following special sequences:
-  %n -- replaced by the doctest buffer's name.
-  %N -- replaced by the doctest buffer's name, with '.doctest'
-        stripped off.
-  %f -- replaced by the doctest buffer's filename."
-  :type 'string
-  :group 'doctest)
-
-(defcustom doctest-optionflags '()
-  "Option flags for doctest"
-  :group 'doctest
-  :type '(repeat (choice (const :tag "Select an option..." "")
-                         (const :tag "Normalize whitespace"
-                                "NORMALIZE_WHITESPACE")
-                         (const :tag "Ellipsis"
-                                "ELLIPSIS")
-                         (const :tag "Don't accept True for 1"
-                                "DONT_ACCEPT_TRUE_FOR_1")
-                         (const :tag "Don't accept <BLANKLINE>"
-                                "DONT_ACCEPT_BLANKLINE")
-                         (const :tag "Ignore Exception detail"
-                                "IGNORE_EXCEPTION_DETAIL")
-                         (const :tag "Report only first failure"
-                                "REPORT_ONLY_FIRST_FAILURE")
-                         )))
-
-(defcustom doctest-async t
-  "If true, then doctest will be run asynchronously."
-  :type 'boolean
-  :group 'doctest)
-
-(defcustom doctest-trim-exceptions t
-  "If true, then any exceptions inserted by doctest-replace-output
-will have the stack trace lines trimmed."
-  :type 'boolean
-  :group 'doctest)
-
-(defcustom doctest-highlight-strings t
-  "If true, then highlight strings.  If you find that doctest-mode
-is responding slowly when you type, turning this off might help."
-  :type 'boolean
-  :group 'doctest)
-
-(defcustom doctest-follow-output t
-  "If true, then when doctest is run asynchronously, the output buffer
-will scroll to display its output as it is generated.  If false, then
-the output buffer not scroll."
-  :type 'boolean
-  :group 'doctest)
-
-(defvar doctest-mode-hook nil
-  "Hook called by `doctest-mode'.")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Fonts
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defface doctest-prompt-face
-  '((((class color) (background dark))
-     (:foreground "#68f"))
-    (t (:foreground "#226")))
-  "Face for Python prompts in doctest examples."
-  :group 'doctest)
-
-(defface doctest-output-face
-  '((((class color) (background dark))
-     (:foreground "#afd"))
-    (t (:foreground "#262")))
-  "Face for the output of doctest examples."
-  :group 'doctest)
-
-(defface doctest-output-marker-face
-  '((((class color) (background dark))
-     (:foreground "#0f0"))
-    (t (:foreground "#080")))
-  "Face for markers in the output of doctest examples."
-  :group 'doctest)
-
-(defface doctest-output-traceback-face
-  '((((class color) (background dark))
-     (:foreground "#f88"))
-    (t (:foreground "#622")))
-  "Face for traceback headers in the output of doctest examples."
-  :group 'doctest)
-
-(defface doctest-results-divider-face
-  '((((class color) (background dark))
-     (:foreground "#08f"))
-    (t (:foreground "#00f")))
-  "Face for dividers in the doctest results window."
-  :group 'doctest)
-
-(defface doctest-results-loc-face
-  '((((class color) (background dark))
-     (:foreground "#0f8"))
-    (t (:foreground "#084")))
-  "Face for location headers in the doctest results window."
-  :group 'doctest)
-
-(defface doctest-results-header-face
-  '((((class color) (background dark))
-     (:foreground "#8ff"))
-    (t (:foreground "#088")))
-  "Face for sub-headers in the doctest results window."
-  :group 'doctest)
-
-(defface doctest-results-selection-face
-  '((((class color) (background dark))
-     (:foreground "#ff0" :background "#008"))
-    (t (:background "#088" :foreground "#fff")))
-  "Face for selected failure's location header in the results window."
-  :group 'doctest)
-
-(defface doctest-selection-face
-  '((((class color) (background dark))
-     (:foreground "#ff0" :background "#00f" :bold t))
-    (t (:foreground "#f00")))
-  "Face for selected example's prompt"
-  :group 'doctest)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Constants
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defconst doctest-prompt-re
-  "^\\(?:\\([ \t]*\\)\\(>>> ?\\|[.][.][.] ?\\)\\([ \t]*\\)\\)"
-  "Regular expression for doctest prompts.  It defines three groups:
-the pre-prompt margin; the prompt; and the post-prompt indentation.")
-
-(defconst doctest-open-block-re
-  "[^\n]+:[ \t]*\\(#.*\\)?$"
-  "Regular expression for a line that opens a block")
-
-(defconst doctest-close-block-re
-  "\\(return\\|raise\\|break\\|continue\\|pass\\)\\b"
-  "Regular expression for a line that closes a block")
-
-(defconst doctest-example-source-re 
-  "^Failed example:\n\\(\n\\|    [^\n]*\n\\)+"
-  "Regular expression for example source in doctest's output.")
-
-(defconst doctest-results-divider-re
-  "^\\([*]\\{60,\\}\\)$"
-  "Regular expression for example dividers in doctest's output.")
-
-(defconst doctest-py24-results-loc-re
-  "^File \"[^\"]+\", line \\([0-9]+\\), in [^\n]+"
-  "Regular expression for example location markers in doctest's output.")
-
-(defconst doctest-py21-results-loc-re
-  "^from line #\\([0-9]+\\) of [^\n]*"
-  "Regular expression for example location markers in doctest's output,
-when the output was generated by an old version of doctest.")
-
-(defconst doctest-results-header-re
-  "^\\([^ \n\t].+:\\|Expected nothing\\|Got nothing\\)$"
-  "Regular expression for example headers in doctest's output.")
-
-(defconst doctest-traceback-header-re
-  "^[ \t]*Traceback (\\(most recent call last\\|innermost last\\)):"
-  "Regular expression for Python traceback headers.")
-
-(defconst doctest-py21-results-re
-  "^from line #"
-  "Regular expression used to test which version of doctest was used.")
-
-;; nb: There's a bug in Python's traceback.print_exception function
-;; which causes SyntaxError exceptions to be displayed incorrectly;
-;; which prevents this regexp from matching.  But there shouldn't be
-;; too many people testing for SyntaxErrors, so I won't worry about
-;; it.
-(defconst doctest-traceback-re
-  (let ((nonprompt
-         ;; This matches any non-blank line that doesn't start with
-         ;; a prompt (... or >>>).
-         (concat 
-          "\\(?:[.][.][^.\n]\\|[>][>][^>\n]\\|"
-          "[.][^.\n]\\|[>][^>\n]\\|[^.>\n \t]\\)[^\n]*")))
-    (concat
-     "^\\(\\([ \t]*\\)Traceback "
-     "(\\(?:most recent call last\\|innermost last\\)):\n\\)"
-     "\\(?:\\2[ \t]+[^ \t\n][^\n]*\n\\)*"
-     "\\(\\(?:\\2" nonprompt "\n\\)"
-        "\\(?:\\2[ \t]*" nonprompt "\n\\)*\\)"))
-  "Regular expression that matches a complete exception traceback.
-It contains three groups: group 1 is the header line; group 2 is
-the indentation; and group 3 is the exception message.")
-  
-(defconst doctest-blankline-re
-  "^[ \t]*<BLANKLINE>"
-  "Regular expression that matches blank line markers in doctest
-output.")
-
-(defconst doctest-outdent-re
-  (concat "\\(" (mapconcat 'identity
-			   '("else:"
-			     "except\\(\\s +.*\\)?:"
-			     "finally:"
-			     "elif\\s +.*:")
-			   "\\|")
-	  "\\)")
-  "Regular expression for a line that should be outdented.  Any line
-that matches `doctest-outdent-re', but does not follow a line matching
-`doctest-no-outdent-re', will be outdented.")
-
-;; It's not clear to me *why* the behavior given by this definition of
-;; doctest-no-outdent-re is desirable; but it's basically just copied
-;; from python-mode.
-(defconst doctest-no-outdent-re
-  (concat
-   "\\("
-   (mapconcat 'identity
-	      (list "try:"
-		    "except\\(\\s +.*\\)?:"
-		    "while\\s +.*:"
-		    "for\\s +.*:"
-		    "if\\s +.*:"
-		    "elif\\s +.*:"
-                    "\\(return\\|raise\\|break\\|continue\\|pass\\)[ \t\n]"
-		    )
-	      "\\|")
-	  "\\)")
-  "Regular expression matching lines not to outdent after.  Any line
-that matches `doctest-outdent-re', but does not follow a line matching
-`doctest-no-outdent-re', will be outdented.")
-
-(defconst doctest-script
-  "\
-from doctest import *
-import sys
-if '%m':
-    import imp
-    try:
-        m = imp.load_source('__imported__', '%m')
-        globs = m.__dict__
-    except Exception, e:
-        print ('doctest-mode encountered an error while importing '
-               'the current buffer:\\n\\n  %s' % e)
-        sys.exit(1)
-else:
-    globs = {}
-doc = open('%t').read()
-if sys.version_info[:2] >= (2,4):
-    test = DocTestParser().get_doctest(doc, globs, '%n', '%f', 0)
-    r = DocTestRunner(optionflags=%l)
-    r.run(test)
-else:
-    Tester(globs=globs).runstring(doc, '%f')"
-  ;; Docstring:
-  "Python script used to run doctest.
-The following special sequences are defined:
-  %n -- replaced by the doctest buffer's name.
-  %f -- replaced by the doctest buffer's filename.
-  %l -- replaced by the doctest flags string.
-  %t -- replaced by the name of the tempfile containing the doctests."
-  )
-
-(defconst doctest-keyword-re
-  (let* ((kw1 (mapconcat 'identity
-                         '("and"      "assert"   "break"   "class"
-                           "continue" "def"      "del"     "elif"
-                           "else"     "except"   "exec"    "for"
-                           "from"     "global"   "if"      "import"
-                           "in"       "is"       "lambda"  "not"
-                           "or"       "pass"     "print"   "raise"
-                           "return"   "while"    "yield"
-                           )
-                         "\\|"))
-         (kw2 (mapconcat 'identity
-                         '("else:" "except:" "finally:" "try:")
-                         "\\|"))
-         (kw3 (mapconcat 'identity
-                         '("ArithmeticError" "AssertionError"
-                           "AttributeError" "DeprecationWarning" "EOFError"
-                           "Ellipsis" "EnvironmentError" "Exception" "False"
-                           "FloatingPointError" "FutureWarning" "IOError"
-                           "ImportError" "IndentationError" "IndexError"
-                           "KeyError" "KeyboardInterrupt" "LookupError"
-                           "MemoryError" "NameError" "None" "NotImplemented"
-                           "NotImplementedError" "OSError" "OverflowError"
-                           "OverflowWarning" "PendingDeprecationWarning"
-                           "ReferenceError" "RuntimeError" "RuntimeWarning"
-                           "StandardError" "StopIteration" "SyntaxError"
-                           "SyntaxWarning" "SystemError" "SystemExit"
-                           "TabError" "True" "TypeError" "UnboundLocalError"
-                           "UnicodeDecodeError" "UnicodeEncodeError"
-                           "UnicodeError" "UnicodeTranslateError"
-                           "UserWarning" "ValueError" "Warning"
-                           "ZeroDivisionError" "__debug__"
-                           "__import__" "__name__" "abs" "apply" "basestring"
-                           "bool" "buffer" "callable" "chr" "classmethod"
-                           "cmp" "coerce" "compile" "complex" "copyright"
-                           "delattr" "dict" "dir" "divmod"
-                           "enumerate" "eval" "execfile" "exit" "file"
-                           "filter" "float" "getattr" "globals" "hasattr"
-                           "hash" "hex" "id" "input" "int" "intern"
-                           "isinstance" "issubclass" "iter" "len" "license"
-                           "list" "locals" "long" "map" "max" "min" "object"
-                           "oct" "open" "ord" "pow" "property" "range"
-                           "raw_input" "reduce" "reload" "repr" "round"
-                           "setattr" "slice" "staticmethod" "str" "sum"
-                           "super" "tuple" "type" "unichr" "unicode" "vars"
-                           "xrange" "zip")
-                         "\\|"))
-         (pseudokw (mapconcat 'identity
-                              '("self" "None" "True" "False" "Ellipsis")
-                              "\\|"))
-         (string (concat "'\\(?:\\\\[^\n]\\|[^\n']*\\)'" "\\|"
-                         "\"\\(?:\\\\[^\n]\\|[^\n\"]*\\)\""))
-         (brk "\\(?:[ \t(]\\|$\\)"))
-    (concat
-     ;; Comments (group 1)
-     "\\(#.*\\)"
-     ;; Function & Class Definitions (groups 2-3)
-     "\\|\\b\\(class\\|def\\)"
-     "[ \t]+\\([a-zA-Z_][a-zA-Z0-9_]*\\)"
-     ;; Builtins preceeded by '.'(group 4)
-     "\\|[.][\t ]*\\(" kw3 "\\)"
-     ;; Keywords & builtins (group 5)
-     "\\|\\b\\(" kw1 "\\|" kw2 "\\|"
-     kw3 "\\|" pseudokw "\\)" brk
-     ;; Decorators (group 6)
-     "\\|\\(@[a-zA-Z_][a-zA-Z0-9_]*\\)"
-     ))
-  "A regular expression used for syntax highlighting of Python
-source code.")
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Syntax Highlighting (font-lock mode)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Define the font-lock keyword table.
-(defconst doctest-font-lock-keywords
-  `(
-    ;; The following pattern colorizes source lines.  In particular,
-    ;; it first matches prompts, and then looks for any of the
-    ;; following matches *on the same line* as the prompt.  It uses
-    ;; the form:
-    ;;
-    ;;   (MATCHER MATCH-HIGHLIGHT
-    ;;            (ANCHOR-MATCHER nil nil MATCH-HIGHLIGHT))
-    ;;
-    ;; See the variable documentation for font-lock-keywords for a
-    ;; description of what each of those means.
-    ("^[ \t]*\\(>>>\\|\\.\\.\\.\\)"
-     (1 'doctest-prompt-face)
-     (doctest-source-matcher
-      nil nil
-      (1 'font-lock-comment-face t t)         ; comments
-      (2 'font-lock-keyword-face t t)         ; def/class
-      (3 'font-lock-type-face t t)            ; func/class name
-      ;; group 4 (builtins preceeded by '.') gets no colorization.
-      (5 'font-lock-keyword-face t t)         ; keywords & builtins
-      (6 'font-lock-preprocessor-face t t)    ; decorators
-      (7 'font-lock-string-face t t)          ; strings
-      ))
-      
-    ;; The following pattern colorizes output lines.  In particular,
-    ;; it uses doctest-output-line-matcher to check if this is an
-    ;; output line, and if so, it colorizes it, and any special
-    ;; markers it contains.
-    (doctest-output-line-matcher
-     (0 'doctest-output-face t)
-     ("\\.\\.\\." (beginning-of-line) (end-of-line)
-      (0 'doctest-output-marker-face t))
-     (,doctest-blankline-re (beginning-of-line) (end-of-line)
-                            (0 'doctest-output-marker-face t))
-     (doctest-traceback-line-matcher (beginning-of-line) (end-of-line)
-                                     (0 'doctest-output-traceback-face t))
-     (,doctest-traceback-header-re (beginning-of-line) (end-of-line)
-                                   (0 'doctest-output-traceback-face t))
-     )
-
-    ;; A PS1 prompt followed by a non-space is an error.
-    ("^[ \t]*\\(>>>[^ \t\n][^\n]*\\)" (1 'font-lock-warning-face t))
-    )
-  "Expressions to highlight in doctest-mode.")
-
-(defconst doctest-results-font-lock-keywords
-  `((,doctest-results-divider-re 
-     (0 'doctest-results-divider-face))
-    (,doctest-py24-results-loc-re 
-     (0 'doctest-results-loc-face))
-    (,doctest-results-header-re 
-     (0 'doctest-results-header-face))
-    (doctest-results-selection-matcher 
-     (0 'doctest-results-selection-face t)))
-  "Expressions to highlight in doctest-results-mode.")
-
-(defun doctest-output-line-matcher (limit)
-  "A `font-lock-keyword' MATCHER that returns t if the current 
-line is the expected output for a doctest example, and if so, 
-sets `match-data' so that group 0 spans the current line."
-  ;; The real work is done by doctest-find-output-line.
-  (when (doctest-find-output-line limit)
-    ;; If we found one, then mark the entire line.
-    (beginning-of-line)
-    (re-search-forward "[^\n]*" limit)))
-
-(defun doctest-traceback-line-matcher (limit)
-  "A `font-lock-keyword' MATCHER that returns t if the current line is
-the beginning of a traceback, and if so, sets `match-data' so that
-group 0 spans the entire traceback.  n.b.: limit is ignored."
-  (beginning-of-line)
-  (when (looking-at doctest-traceback-re)
-      (goto-char (match-end 0))
-      t))
-
-(defun doctest-source-matcher (limit)
-  "A `font-lock-keyword' MATCHER that returns t if the current line
-contains a Python source expression that should be highlighted
-after the point.  If so, it sets `match-data' to cover the string
-literal.  The groups in `match-data' should be interpreted as follows:
-
-  Group 1: comments
-  Group 2: def/class
-  Group 3: function/class name
-  Group 4: builtins preceeded by '.'
-  Group 5: keywords & builtins
-  Group 6: decorators
-  Group 7: strings
-"
-  (let ((matchdata nil))
-    ;; First, look for string literals.
-    (when doctest-highlight-strings
-      (save-excursion
-        (when (doctest-string-literal-matcher limit)
-          (setq matchdata
-                (list (match-beginning 0) (match-end 0)
-                      nil nil nil nil nil nil nil nil nil nil nil nil
-                      (match-beginning 0) (match-end 0))))))
-    ;; Then, look for other keywords.  If they occur before the
-    ;; string literal, then they take precedence.
-    (save-excursion
-      (when (and (re-search-forward doctest-keyword-re limit t)
-                 (or (null matchdata)
-                     (< (match-beginning 0) (car matchdata))))
-        (setq matchdata (match-data))))
-    (when matchdata
-      (set-match-data matchdata)
-      (goto-char (match-end 0))
-      t)))
-          
-(defun doctest-string-literal-matcher (limit &optional debug)
-  "A `font-lock-keyword' MATCHER that returns t if the current line
-contains a string literal starting at or after the point.  If so, it
-expands `match-data' to cover the string literal.  This matcher uses
-`doctest-statement-info' to collect information about strings that
-continue over multiple lines.  It therefore might be a little slow for
-very large statements."
-  (let* ((stmt-info (doctest-statement-info))
-         (quotes (reverse (nth 5 stmt-info)))
-         (result nil))
-    (if debug (doctest-debug "quotes %s" quotes))
-    (while (and quotes (null result))
-      (let* ((quote (pop quotes))
-             (start (car quote))
-             (end (min limit (or (cdr quote) limit))))
-        (if debug (doctest-debug "quote %s-%s pt=%s lim=%s"
-                                 start end (point) limit))
-        (when (or (and (<= (point) start) (< start limit))
-                  (and (< start (point)) (< (point) end)))
-          (setq start (max start (point)))
-          (set-match-data (list start end))
-          (if debug (doctest-debug "marking string %s" (match-data)))
-          (goto-char end)
-          (setq result t))))
-    result))
-   
-(defun doctest-results-selection-matcher (limit)
-  "Matches from `doctest-selected-failure' to the end of the
-line.  This is used to highlight the currently selected failure."
-  (when (and doctest-selected-failure
-	     (<= (point) doctest-selected-failure)
-	     (< doctest-selected-failure limit))
-    (goto-char doctest-selected-failure)
-    (re-search-forward "[^\n]+" limit)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Source code editing & indentation
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun doctest-indent-source-line (&optional dedent-only)
-  "Re-indent the current line, as doctest source code.  I.e., add a
-prompt to the current line if it doesn't have one, and re-indent the
-source code (to the right of the prompt).  If `dedent-only' is true,
-then don't increase the indentation level any."
-  (interactive "*")
-  (let ((indent-end nil))
-    (save-excursion
-      (beginning-of-line)
-      (let ((new-indent (doctest-current-source-line-indentation dedent-only))
-            (new-margin (doctest-current-source-line-margin))
-            (line-had-prompt (looking-at doctest-prompt-re)))
-        ;; Delete the old prompt (if any).
-        (when line-had-prompt
-          (goto-char (match-beginning 2))
-          (delete-char (- (match-end 2) (match-beginning 2))))
-        ;; Delete the old indentation.
-        (delete-backward-char (skip-chars-forward " \t"))
-        ;; If it's a continuation line, or a new PS1 prompt,
-        ;; then copy the margin.
-        (when (or new-indent (not line-had-prompt))
-          (beginning-of-line)
-          (delete-backward-char (skip-chars-forward " \t"))
-          (insert-char ?\  new-margin))
-        ;; Add the new prompt.
-        (insert-string (if new-indent "... " ">>> "))
-        ;; Add the new indentation
-        (if new-indent (insert-char ?\  new-indent))
-        (setq indent-end (point))))
-    ;; If we're left of the indentation end, then move up to the
-    ;; indentation end.
-    (if (< (point) indent-end) (goto-char indent-end))))
-
-(defun doctest-current-source-line-indentation (&optional dedent-only)
-  "Return the post-prompt indent to use for this line.  This is an
-integer for a continuation lines, and nil for non-continuation lines."
-  (save-excursion
-    ;; Examine the previous doctest line (if present).
-    (let* ((prev-stmt-info (doctest-prev-statement-info))
-           (prev-stmt-indent (nth 0 prev-stmt-info)) 
-           (continuation-indent (nth 1 prev-stmt-info))
-           (prev-stmt-opens-block (nth 2 prev-stmt-info))
-           (prev-stmt-closes-block (nth 3 prev-stmt-info))
-           (prev-stmt-blocks-outdent (nth 4 prev-stmt-info))
-           )
-      ;; Examine this doctest line.
-      (let* ((curr-line-indent 0)
-             (curr-line-outdented nil))
-        (beginning-of-line)
-        (when (looking-at doctest-prompt-re)
-          (setq curr-line-indent (- (match-end 3) (match-beginning 3)))
-          (goto-char (match-end 3)))
-        (setq curr-line-outdented (and (looking-at doctest-outdent-re)
-                                       (not prev-stmt-blocks-outdent)))
-        ;; Compute the overall indent.
-        (let ((indent (or continuation-indent 
-                          (+ prev-stmt-indent
-                             (if curr-line-outdented -4 0)
-                             (if prev-stmt-opens-block 4 0)
-                             (if prev-stmt-closes-block -4 0)))))
-          ;; If dedent-only is true, then make sure we don't indent.
-          (when dedent-only 
-            (setq indent (min indent curr-line-indent)))
-          ;; If indent=0 and we're not outdented, then set indent to
-          ;; nil (to signify the start of a new source example).
-          (when (and (= indent 0)
-                     (not (or curr-line-outdented continuation-indent)))
-            (setq indent nil))
-          ;; Return the indentation.
-          indent)))))
-
-(defun doctest-prev-statement-info (&optional debug)
-  (save-excursion
-    (forward-line -1)
-    (doctest-statement-info debug)))
-
-(defun doctest-statement-info (&optional debug)
-  "Collect info about the previous statement, and return it as a list:
-
-  (INDENT, CONTINUATION, OPENS-BLOCK, CLOSES-BLOCK, BLOCKS-OUTDENT,
-   QUOTES)
-
-INDENT -- The indentation of the previous statement (after the prompt)
-
-CONTINUATION -- If the previous statement is incomplete (e.g., has an
-open paren or quote), then this is the appropriate indentation
-level; otherwise, it's nil.
-
-OPENS-BLOCK -- True if the previous statement opens a Python control
-block.
-
-CLOSES-BLOCK -- True if the previous statement closes a Python control
-block.
-
-BLOCKS-OUTDENT -- True if the previous statement should 'block the
-next statement from being considered an outdent.
-
-QUOTES -- A list of (START . END) pairs for all quotation strings.
-"
-  (save-excursion
-    (end-of-line)
-    (let ((end (point)))
-      (while (and (doctest-on-source-line-p "...") (= (forward-line -1) 0)))
-      (cond
-       ;; If there's no previous >>> line, then give up.
-       ((not (doctest-on-source-line-p ">>>"))
-        '(0 nil nil nil nil))
-       
-       ;; If there is a previous statement, walk through the source
-       ;; code, checking for operators that may be of interest.
-       (t 
-        (beginning-of-line)
-        (let* ((quote-mark nil) (nesting 0) (indent-stack '())
-               (stmt-indent 0)
-               (stmt-opens-block nil)
-               (stmt-closes-block nil)
-               (stmt-blocks-outdent nil)
-               (quotes '())
-               (elt-re (concat "\\\\[^\n]\\|"
-                               "(\\|)\\|\\[\\|\\]\\|{\\|}\\|"
-                               "\"\"\"\\|\'\'\'\\|\"\\|\'\\|"
-                               "#[^\n]*\\|" doctest-prompt-re)))
-          (while (re-search-forward elt-re end t)
-            (let* ((elt (match-string 0))
-                   (elt-first-char (substring elt 0 1)))
-              (if debug (doctest-debug "Debug: %s" elt))
-              (cond
-               ;; Close quote -- set quote-mark back to nil.  The
-               ;; second case is for cases like: '  '''
-               (quote-mark
-                (cond
-                 ((equal quote-mark elt)
-                  (setq quote-mark nil)
-                  (setcdr (car quotes) (point)))
-                 ((equal quote-mark elt-first-char)
-                  (setq quote-mark nil)
-                  (setcdr (car quotes) (point))
-                  (backward-char 2))))
-               ;; Prompt -- check if we're starting a new stmt.  If so,
-               ;; then collect various info about it.
-               ((string-match doctest-prompt-re elt)
-                (when (and (null quote-mark) (= nesting 0))
-                  (let ((indent (- (match-end 3) (match-end 2))))
-                    (unless (looking-at "[ \t]*\n")
-                      (setq stmt-indent indent)
-                      (setq stmt-opens-block
-                            (looking-at doctest-open-block-re))
-                      (setq stmt-closes-block
-                            (looking-at doctest-close-block-re))
-                      (setq stmt-blocks-outdent
-                            (looking-at doctest-no-outdent-re))))))
-               ;; Open paren -- increment nesting, and update indent-stack.
-               ((string-match "(\\|\\[\\|{" elt-first-char)
-                (let ((elt-pos (point))
-                      (at-eol (looking-at "[ \t]*\n"))
-                      (indent 0))
-                  (save-excursion 
-                    (re-search-backward doctest-prompt-re)
-                    (if at-eol
-                        (setq indent (+ 4 (- (match-end 3) (match-end 2))))
-                      (setq indent (- elt-pos (match-end 2))))
-                    (push indent indent-stack)))
-                (setq nesting (+ nesting 1)))
-               ;; Close paren -- decrement nesting, and pop indent-stack.
-               ((string-match ")\\|\\]\\|}" elt-first-char)
-                (setq indent-stack (cdr indent-stack))
-                (setq nesting (max 0 (- nesting 1))))
-               ;; Open quote -- set quote-mark.
-               ((string-match "\"\\|\'" elt-first-char)
-                (push (cons (- (point) (length elt)) nil) quotes)
-                (setq quote-mark elt)))))
-        
-          (let* ((continuation-indent
-                 (cond
-                  (quote-mark 0)
-                  ((> nesting 0) (if (null indent-stack) 0 (car indent-stack)))
-                  (t nil)))
-                 (result 
-                  (list stmt-indent continuation-indent
-                        stmt-opens-block stmt-closes-block
-                        stmt-blocks-outdent quotes)))
-            (if debug (doctest-debug "Debug: %s" result))
-            result)))))))
-
-(defun doctest-current-source-line-margin ()
-  "Return the pre-prompt margin to use for this source line.  This is
-copied from the most recent source line, or set to
-`doctest-default-margin' if there are no preceeding source lines."
-  (save-excursion
-    (save-restriction
-      (when (doctest-in-mmm-docstring-overlay)
-        (doctest-narrow-to-mmm-overlay))
-      (beginning-of-line)
-      (forward-line -1)
-      (while (and (not (doctest-on-source-line-p))
-                  (re-search-backward doctest-prompt-re nil t))))
-    (cond ((looking-at doctest-prompt-re)
-           (- (match-end 1) (match-beginning 1)))
-          ((doctest-in-mmm-docstring-overlay)
-           (doctest-default-margin-in-mmm-docstring-overlay))
-          (t
-           doctest-default-margin))))
-
-(defun doctest-electric-backspace ()
-  "Delete the preceeding character, level of indentation, or
-prompt.  
-
-If point is at the leftmost column, delete the preceding newline.
-
-Otherwise, if point is at the first non-whitespace character
-following an indented source line's prompt, then reduce the
-indentation to the next multiple of 4; and update the source line's
-prompt, when necessary.
-
-Otherwise, if point is at the first non-whitespace character
-following an unindented source line's prompt, then remove the
-prompt (converting the line to an output line or text line).
-
-Otherwise, if point is at the first non-whitespace character of a
-line, the delete the line's indentation.
-
-Otherwise, delete the preceeding character.
-"
-  (interactive "*")
-  (cond 
-   ;; Beginning of line: delete preceeding newline.
-   ((bolp) (backward-delete-char 1))
-      
-   ;; First non-ws char following prompt: dedent or remove prompt.
-   ((and (looking-at "[^ \t\n]\\|$") (doctest-looking-back doctest-prompt-re))
-    (let* ((prompt-beg (match-beginning 2))
-	   (indent-beg (match-beginning 3)) (indent-end (match-end 3))
-	   (old-indent (- indent-end indent-beg))
-	   (new-indent (* (/ (- old-indent 1) 4) 4)))
-      (cond
-       ;; Indented source line: dedent it.
-       ((> old-indent 0)
-	(goto-char indent-beg)
-	(delete-region indent-beg indent-end)
-	(insert-char ?\  new-indent)
-	;; Change prompt to PS1, when appropriate.
-	(when (and (= new-indent 0) (not (looking-at doctest-outdent-re)))
-	  (delete-backward-char 4)
-	  (insert-string ">>> ")))
-       ;; Non-indented source line: remove prompt.
-       (t
-	(goto-char indent-end)
-	(delete-region prompt-beg indent-end)))))
-
-   ;; First non-ws char of a line: delete all indentation.
-   ((and (looking-at "[^ \n\t]\\|$") (doctest-looking-back "^[ \t]+"))
-    (delete-region (match-beginning 0) (match-end 0)))
-
-   ;; Otherwise: delete a character.
-   (t
-    (backward-delete-char 1))))
-
-(defun doctest-newline-and-indent ()
-  "Insert a newline, and indent the new line appropriately.
-
-If the current line is a source line containing a bare prompt,
-then clear the current line, and insert a newline.
-
-Otherwise, if the current line is a source line, then insert a
-newline, and add an appropriately indented prompt to the new
-line.
-
-Otherwise, if the current line is an output line, then insert a
-newline and indent the new line to match the example's margin.
-
-Otherwise, insert a newline.
-
-If `doctest-avoid-trailing-whitespace' is true, then clear any
-whitespace to the left of the point before inserting a newline.
-"
-  (interactive "*")
-  ;; If we're avoiding trailing spaces, then delete WS before point.
-  (if doctest-avoid-trailing-whitespace
-      (delete-char (- (skip-chars-backward " \t"))))     
-  (cond 
-   ;; If we're on an empty prompt, delete it.
-   ((doctest-on-empty-source-line-p)
-    (delete-region (match-beginning 0) (match-end 0))
-    (insert-char ?\n 1))
-   ;; If we're on a doctest line, add a new prompt.
-   ((doctest-on-source-line-p)
-    (insert-char ?\n 1)
-    (doctest-indent-source-line))
-   ;; If we're in doctest output, indent to the margin.
-   ((doctest-on-output-line-p)
-    (insert-char ?\n 1)
-    (insert-char ?\  (doctest-current-source-line-margin)))
-   ;; Otherwise, just add a newline.
-   (t (insert-char ?\n 1))))
-
-(defun doctest-electric-colon ()
-  "Insert a colon, and dedent the line when appropriate."
-  (interactive "*")
-  (insert-char ?: 1)
-  (when (doctest-on-source-line-p)
-    (doctest-indent-source-line t)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Code Execution
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun doctest-execute ()
-  "Run doctest on the current buffer, or on the current docstring
-if the point is inside an `mmm-mode' `doctest-docstring' region.
-Display the results in the *doctest-output* buffer."
-  (interactive)
-  (doctest-execute-region (point-min) (point-max) nil t))
-  
-(defun doctest-execute-with-diff ()
-  "Run doctest on the current buffer, or on the current docstring
-if the point is inside an `mmm-mode' `doctest-docstring' region.
-Display the results in the *doctest-output* buffer, using diff format."
-  (interactive)
-  (doctest-execute-region (point-min) (point-max) t t))
-  
-(defun doctest-execute-buffer-with-diff ()
-  "Run doctest on the current buffer, and display the results in the 
-*doctest-output* buffer, using the diff format."
-  (interactive)
-  (doctest-execute-region (point-min) (point-max) t nil))
-
-(defun doctest-execute-buffer ()
-  "Run doctest on the current buffer, and display the results in the 
-*doctest-output* buffer."
-  (interactive)
-  (doctest-execute-region (point-min) (point-max) nil nil))
-
-(defun doctest-execute-region (start end &optional diff
-                                     check-for-mmm-docstring-overlay)
-  "Run doctest on the current buffer, and display the results in the 
-*doctest-output* buffer."
-  (interactive "r")
-  ;; If it's already running, give the user a chance to restart it.
-  (when (doctest-process-live-p doctest-async-process)
-    (when (y-or-n-p "Doctest is already running.  Restart it? ")
-      (doctest-cancel-async-process)
-      (message "Killing doctest...")))
-  (cond
-   ((and doctest-async (doctest-process-live-p doctest-async-process))
-    (message "Can't run two doctest processes at once!"))
-   (t
-    (let* ((results-buf-name (doctest-results-buffer-name))
-           (in-docstring (and check-for-mmm-docstring-overlay
-                              (doctest-in-mmm-docstring-overlay)))
-           (temp (doctest-temp-name)) (dir doctest-temp-directory)
-           (input-file (expand-file-name (concat temp ".py") dir))
-           (globs-file (when in-docstring
-                         (expand-file-name (concat temp "-globs.py") dir)))
-           (cur-buf (current-buffer))
-           (in-buf (get-buffer-create "*doctest-input*"))
-           (script (doctest-script input-file globs-file diff)))
-      ;; If we're in a docstring, narrow start & end.
-      (when in-docstring
-        (let ((bounds (doctest-mmm-overlay-bounds)))
-          (setq start (max start (car bounds))
-                end (min end (cdr bounds)))))
-      ;; Write the doctests to a file.
-      (save-excursion
-        (goto-char (min start end))
-        (let ((lineno (doctest-line-number)))
-          (set-buffer in-buf)
-          ;; Add blank lines, to keep line numbers the same:
-          (dotimes (n (- lineno 1)) (insert-string "\n"))
-          ;; Add the selected region
-          (insert-buffer-substring cur-buf start end)
-          ;; Write it to a file
-          (write-file input-file)))
-      ;; If requested, write the buffer to a file for use as globs.
-      (when globs-file
-        (let ((cur-buf-start (point-min)) (cur-buf-end (point-max)))
-          (save-excursion
-            (set-buffer in-buf)
-            (delete-region (point-min) (point-max))
-            (insert-buffer-substring cur-buf cur-buf-start cur-buf-end)
-            (write-file globs-file))))
-      ;; Dispose of in-buf (we're done with it now.
-      (kill-buffer in-buf)
-      ;; Prepare the results buffer.  Clear it, if it contains
-      ;; anything, and set its mode.
-      (setq doctest-results-buffer (get-buffer-create results-buf-name))
-      (save-excursion
-        (set-buffer doctest-results-buffer)
-        (toggle-read-only 0)
-        (delete-region (point-min) (point-max))
-        (doctest-results-mode)
-        (setq doctest-source-buffer cur-buf)
-        )
-      ;; Add markers to examples, and record what line number each one
-      ;; starts at.  That way, if the input buffer is edited, we can
-      ;; still find corresponding examples in the output.
-      (doctest-mark-examples)
-
-      ;; Run doctest
-      (cond (doctest-async
-             ;; Asynchronous mode:
-             (let ((process (start-process "*doctest*" doctest-results-buffer
-                                           doctest-python-command
-                                           "-c" script)))
-               ;; Store some information about the process.
-               (setq doctest-async-process-buffer cur-buf)
-               (setq doctest-async-process process)
-               (push input-file doctest-async-process-tempfiles)
-               (when globs-file
-                 (push globs-file doctest-async-process-tempfiles))
-               ;; Set up a sentinel to respond when it's done running.
-               (set-process-sentinel process 'doctest-async-process-sentinel)
-
-               ;; Show the output window.
-               (let ((w (display-buffer doctest-results-buffer)))
-                 (when doctest-follow-output
-                   ;; Insert a newline, which will move the buffer's
-                   ;; point past the process's mark -- this causes the
-                   ;; window to scroll as new output is generated.
-                   (save-current-buffer
-                     (set-buffer doctest-results-buffer)
-                     (insert-string "\n")
-                     (set-window-point w (point)))))
-
-               ;; Let the user know the process is running.
-               (doctest-update-mode-line ":running")
-               (message "Running doctest...")))
-            (t
-             ;; Synchronous mode:
-             (call-process doctest-python-command nil
-                           doctest-results-buffer t "-c" script)
-             (doctest-handle-output)
-             (delete-file input-file)
-             (when globs-file
-               (delete-file globs-file))))))))
-
-(defun doctest-handle-output ()
-  "This function, which is called after the 'doctest' process spawned
-by doctest-execute-buffer has finished, checks the doctest results
-buffer.  If that buffer is empty, it reports no errors and hides it;
-if that buffer is not empty, it reports that errors occured, displays
-the buffer, and runs doctest-postprocess-results."
-  ;; If any tests failed, display them.
-  (cond ((not (buffer-live-p doctest-results-buffer))
-         (doctest-warn "Results buffer not found!"))
-        ((> (buffer-size doctest-results-buffer) 1)
-         (display-buffer doctest-results-buffer)
-         (doctest-postprocess-results)
-         (let ((num (length doctest-example-markers)))
-           (message "%d doctest example%s failed!" num
-                    (if (= num 1) "" "s"))))
-        (t
-         (display-buffer doctest-results-buffer)
-         (delete-windows-on doctest-results-buffer)
-         (message "All doctest examples passed!"))))
-         
-(defun doctest-async-process-sentinel (process state)
-  "A process sentinel, called when the asynchronous doctest process
-completes, which calls doctest-handle-output."
-  ;; Check to make sure we got the process we're expecting.  On
-  ;; some operating systems, this will end up getting called twice
-  ;; when we use doctest-cancel-async-process; this check keeps us
-  ;; from trying to clean up after the same process twice (since we
-  ;; set doctest-async-process to nil when we're done).
-  (when (and (equal process doctest-async-process)
-             (buffer-live-p doctest-async-process-buffer))
-    (save-current-buffer
-      (set-buffer doctest-async-process-buffer)
-      (cond ((not (buffer-live-p doctest-results-buffer))
-             (doctest-warn "Results buffer not found!"))
-            ((equal state "finished\n")
-             (doctest-handle-output)
-             (let ((window (get-buffer-window
-                            doctest-async-process-buffer t)))
-               (when window (set-window-point window (point)))))
-            ((equal state "killed\n")
-             (message "Doctest killed."))
-            (t
-             (message "Doctest failed -- %s" state)
-             (display-buffer doctest-results-buffer)))
-      (doctest-update-mode-line "")
-      (while doctest-async-process-tempfiles
-        (delete-file (pop doctest-async-process-tempfiles)))
-      (setq doctest-async-process nil))))
-
-(defun doctest-cancel-async-process ()
-  "If a doctest process is running, then kill it."
-  (interactive "")
-  (when (doctest-process-live-p doctest-async-process)
-    ;; Update the modeline
-    (doctest-update-mode-line ":killing")
-    ;; Kill the process.
-    (kill-process doctest-async-process)
-    ;; Run the sentinel.  (Depending on what OS we're on, the sentinel
-    ;; may end up getting called once or twice.)
-    (doctest-async-process-sentinel doctest-async-process "killed\n")
-    ))
-
-(defun doctest-postprocess-results ()
-  "Post-process the doctest results buffer: check what version of
-doctest was used, and set doctest-results-py-version accordingly;
-turn on read-only mode; filter the example markers; hide the example
-source (if `doctest-hide-example-source' is non-nil); and select the
-first failure."
-  (save-excursion
-    (set-buffer doctest-results-buffer)
-    ;; Check if we're using an old doctest version.
-    (goto-char (point-min))
-    (if (re-search-forward doctest-py21-results-re nil t)
-        (setq doctest-results-py-version 'py21)
-      (setq doctest-results-py-version 'py24))
-    ;; Turn on read-only mode.
-    (toggle-read-only t))
-  
-  (doctest-filter-example-markers)
-  (if doctest-hide-example-source
-      (doctest-hide-example-source))
-  (doctest-next-failure 1))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Markers
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun doctest-mark-examples ()
-  "Add a marker at the beginning of every (likely) example in the
-input buffer; and create a list, `doctest-example-markers',
-which maps from markers to the line numbers they originally occured
-on.  This will allow us to find the corresponding example in the
-doctest output, even if the input buffer is edited."
-  (dolist (marker-info doctest-example-markers)
-    (set-marker (car marker-info) nil))
-  (setq doctest-example-markers '())
-  (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward "^ *>>> " nil t)
-      (backward-char 4)
-      (push (cons (point-marker) (doctest-line-number))
-            doctest-example-markers)
-      (forward-char 4))))
-
-(defun doctest-filter-example-markers ()
-  "Remove any entries from `doctest-example-markers' that do not
-correspond to a failed example."
-  (let ((filtered nil) (markers doctest-example-markers))
-    (save-excursion
-      (set-buffer doctest-results-buffer)
-      (goto-char (point-max))
-      (while (re-search-backward (doctest-results-loc-re) nil t)
-        (let ((lineno (string-to-int (match-string 1))))
-          (when (equal doctest-results-py-version 'py21)
-            (setq lineno (+ lineno 1)))
-          (while (and markers (< lineno (cdar markers)))
-            (set-marker (caar markers) nil)
-            (setq markers (cdr markers)))
-          (if (and markers (= lineno (cdar markers)))
-              (push (pop markers) filtered)
-            (doctest-warn "Example expected on line %d but not found %s"
-                          lineno markers)))))
-    (dolist (marker-info markers)
-      (set-marker (car marker-info) nil))
-    (setq doctest-example-markers filtered)))
-                       
-(defun doctest-prev-example-marker ()
-  "Helper for doctest-replace-output: move to the preceeding example
-marker, and return the corresponding 'original' lineno.  If none is
-found, return nil."
-  (let ((lineno nil)
-        (pos nil))
-    (save-excursion
-      (end-of-line)
-      (when (re-search-backward "^\\( *\\)>>> " nil t)
-        (goto-char (match-end 1))
-        (dolist (marker-info doctest-example-markers)
-          (when (= (marker-position (car marker-info)) (point))
-            (setq lineno (cdr marker-info))
-            (setq pos (point))))))
-    (unless (null lineno)
-      (goto-char pos)
-      lineno)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Navigation
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun doctest-next-failure (count)
-  "Move to the top of the next failing example, and highlight the
-example's failure description in *doctest-output*."
-  (interactive "p")
-  (cond
-   ((and doctest-async (doctest-process-live-p doctest-async-process))
-    (message "Wait for doctest to finish running!"))
-   ((not (doctest-results-buffer-valid-p))
-    (message "Run doctest first! (C-c C-c)"))
-   ((equal count 0)
-    t)
-   (t
-    (let ((marker nil) (example-markers doctest-example-markers)
-          (results-window (display-buffer doctest-results-buffer)))
-      (save-excursion
-        (set-buffer doctest-results-buffer)
-        ;; Pick up where we left off.
-        ;; (nb: doctest-selected-failure is buffer-local)
-        (goto-char (or doctest-selected-failure (point-min)))
-        ;; Skip past anything on *this* line.
-        (if (>= count 0) (end-of-line) (beginning-of-line))
-        ;; Look for the next failure
-        (when 
-            (if (>= count 0)
-                (re-search-forward (doctest-results-loc-re) nil t count)
-              (re-search-backward (doctest-results-loc-re) nil t (- count)))
-          ;; We found a failure:
-          (let ((old-selected-failure doctest-selected-failure))
-            (beginning-of-line)
-            ;; Extract the line number for the doctest file.
-            (let ((orig-lineno (string-to-int (match-string 1))))
-              (when (equal doctest-results-py-version 'py21)
-                (setq orig-lineno (+ orig-lineno 1)))
-              (dolist (marker-info example-markers)
-                (when (= orig-lineno (cdr marker-info))
-                  (setq marker (car marker-info)))))
-              
-            ;; Update the window cursor.
-            (beginning-of-line)
-            (set-window-point results-window (point))
-            ;; Store our position for next time.
-            (setq doctest-selected-failure (point))
-            ;; Update selection.
-            (doctest-fontify-line old-selected-failure)
-            (doctest-fontify-line doctest-selected-failure))))
-      
-      (cond
-       ;; We found a failure -- move point to the selected failure.
-       (marker
-        (goto-char (marker-position marker))
-        (beginning-of-line))
-       ;; We didn't find a failure, but there is one -- wrap.
-       ((> (length doctest-example-markers) 0)
-        (if (>= count 0) (doctest-first-failure) (doctest-last-failure)))
-       ;; We didn't find a failure -- alert the user.
-       (t (message "No failures found!")))))))
-
-(defun doctest-prev-failure (count)
-  "Move to the top of the previous failing example, and highlight
-the example's failure description in *doctest-output*."
-  (interactive "p")
-  (doctest-next-failure (- count)))
-
-(defun doctest-first-failure ()
-  "Move to the top of the first failing example, and highlight
-the example's failure description in *doctest-output*."
-  (interactive)
-  (if (buffer-live-p doctest-results-buffer)
-      (save-excursion
-        (set-buffer doctest-results-buffer)
-        (let ((old-selected-failure doctest-selected-failure))
-          (setq doctest-selected-failure (point-min))
-          (doctest-fontify-line old-selected-failure))))
-  (doctest-next-failure 1))
-
-(defun doctest-last-failure ()
-  "Move to the top of the last failing example, and highlight
-the example's failure description in *doctest-output*."
-  (interactive)
-  (if (buffer-live-p doctest-results-buffer)
-      (save-excursion
-        (set-buffer doctest-results-buffer)
-        (let ((old-selected-failure doctest-selected-failure))
-          (setq doctest-selected-failure (point-max))
-          (doctest-fontify-line old-selected-failure))))
-  (doctest-next-failure -1))
-
-(defun doctest-select-failure ()
-  "Move to the top of the currently selected example, and select that
-example in the source buffer.  Intended for use in the results
-buffer."
-  (interactive)
-  (re-search-backward doctest-results-divider-re)
-  (let ((old-selected-failure doctest-selected-failure))
-    (setq doctest-selected-failure (point))
-    (doctest-fontify-line doctest-selected-failure)
-    (doctest-fontify-line old-selected-failure))
-  (pop-to-buffer doctest-source-buffer)
-  (doctest-next-failure 1))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Replace Output
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun doctest-replace-output ()
-  "Move to the top of the closest example, and replace its output
-with the 'got' output from the *doctest-output* buffer.  An error is
-displayed if the chosen example is not listed in *doctest-output*, or
-if the 'expected' output for the example does not exactly match the
-output listed in the source buffer.  The user is asked to confirm the
-replacement."
-  (interactive)
-  ;; Move to the beginning of the example.
-  (cond
-   ((and doctest-async (doctest-process-live-p doctest-async-process))
-    (message "Wait for doctest to finish running!"))
-   ((not (doctest-results-buffer-valid-p))
-    (message "Run doctest first! (C-c C-c)"))
-   ((save-excursion (set-buffer doctest-results-buffer)
-                    (equal doctest-results-py-version 'py21))
-    (error "doctest-replace-output requires python 2.4+"))
-   (t
-    (save-excursion
-      (save-restriction
-        (when (doctest-in-mmm-docstring-overlay)
-          (doctest-narrow-to-mmm-overlay))
-            
-        (let* ((orig-buffer (current-buffer))
-               ;; Find an example, and look up its original lineno.
-               (lineno (doctest-prev-example-marker))
-               ;; Find the example's indentation.
-               (prompt-indent (doctest-line-indentation)))
-        
-          ;; Switch to the output buffer, and look for the example.
-          ;; If we don't find one, complain.
-          (cond
-           ((null lineno) (message "Doctest example not found"))
-           (t
-            (set-buffer doctest-results-buffer)
-            (goto-char (point-min))
-            (let ((output-re (format "^File .*, line %s," lineno)))
-              (when (not (re-search-forward output-re nil t))
-                (message "This doctest example did not fail")
-                (setq lineno nil)))))
-
-          ;; If we didn't find an example, give up.
-          (when (not (null lineno))
-            ;; Get the output's 'expected' & 'got' texts.
-            (let ((doctest-got nil) (doctest-expected nil) (header nil))
-              (while (setq header (doctest-results-next-header))
-                (cond
-                 ((equal header "Failed example:")
-                  t)
-                 ((equal header "Expected nothing")
-                  (setq doctest-expected ""))
-                 ((equal header "Expected:")
-                  (unless (re-search-forward "^\\(\\(    \\).*\n\\)*" nil t)
-                    (error "Error parsing doctest output"))
-                  (setq doctest-expected (doctest-replace-regexp-in-string
-                                          "^    " prompt-indent
-                                          (match-string 0))))
-                 ((equal header "Got nothing")
-                  (setq doctest-got ""))
-                 ((or (equal header "Got:") (equal header "Exception raised:"))
-                  (unless (re-search-forward "^\\(\\(    \\).*\n\\)*" nil t)
-                    (error "Error parsing doctest output"))
-                  (setq doctest-got (doctest-replace-regexp-in-string
-                                     "^    " prompt-indent (match-string 0))))
-                 ((string-match "^Differences" header)
-                  (error (concat "doctest-replace-output can not be used "
-                                 "with diff style output")))
-                 (t (error "Unexpected header %s" header))))
-
-              ;; Go back to the source buffer.
-              (set-buffer orig-buffer)
-          
-              ;; Skip ahead to the output.
-              (beginning-of-line)
-              (unless (re-search-forward "^ *>>>.*")
-                (error "Error parsing doctest output"))
-              (re-search-forward "\\(\n *\\.\\.\\..*\\)*\n?")
-              (when (looking-at "\\'") (insert-char ?\n))
-
-              ;; Check that the output matches.
-              (let ((start (point)) end)
-                (cond ((re-search-forward "^ *\\(>>>.*\\|$\\)" nil t)
-                       (setq end (match-beginning 0)))
-                      (t
-                       (goto-char (point-max))
-                       (insert-string "\n")
-                       (setq end (point-max))))
-                (when (and doctest-expected
-                           (not (equal (buffer-substring start end)
-                                       doctest-expected)))
-                  (warn "{%s} {%s}" (buffer-substring start end)
-                        doctest-expected)
-                  (error (concat "This example's output has been modified "
-                                 "since doctest was last run")))
-                (setq doctest-expected (buffer-substring start end))
-                (goto-char end))
-
-              ;; Trim exceptions
-              (when (and doctest-trim-exceptions
-                         (string-match doctest-traceback-re
-                                       doctest-got))
-                (let ((s1 0) (e1 (match-end 1))
-                      (s2 (match-beginning 2)) (e2 (match-end 2))
-                      (s3 (match-beginning 3)) (e3 (length doctest-got)))
-                  (setq doctest-got
-                        (concat (substring doctest-got s1 e1)
-                                (substring doctest-got s2 e2) "  . . .\n"
-                                (substring doctest-got s3 e3)))))
-              
-              ;; Confirm it with the user.
-              (let ((confirm-buffer (get-buffer-create "*doctest-confirm*")))
-                (set-buffer confirm-buffer)
-                ;; Erase anything left over in the buffer.
-                (delete-region (point-min) (point-max))
-                ;; Write a confirmation message
-                (if (equal doctest-expected "")
-                    (insert-string "Replace nothing\n")
-                  (insert-string (concat "Replace:\n" doctest-expected)))
-                (if (equal doctest-got "")
-                    (insert-string "With nothing\n")
-                  (insert-string (concat "With:\n" doctest-got)))
-                (let ((confirm-window (display-buffer confirm-buffer)))
-                  ;; Shrink the confirm window.
-                  (shrink-window-if-larger-than-buffer confirm-window)
-                  ;; Return to the original buffer.
-                  (set-buffer orig-buffer)
-                  ;; Match the old expected region.
-                  (when doctest-expected
-                    (search-backward doctest-expected))
-                  (when (equal doctest-expected "") (backward-char 1))
-                  ;; Get confirmation & do the replacement
-                  (widen)
-                  (cond ((y-or-n-p "Ok to replace? ")
-                         (when (equal doctest-expected "") (forward-char 1))
-                         (replace-match doctest-got t t)
-                         (message "Replaced."))
-                        (t
-                         (message "Replace cancelled.")))
-                  ;; Clean up our confirm window
-                  (kill-buffer confirm-buffer)
-                  (delete-window confirm-window)))))))))))
-
-(defun doctest-results-next-header ()
-  "Move to the next header in the doctest results buffer, and return
-the string contents of that header.  If no header is found, return
-nil."
-  (if (re-search-forward (concat doctest-results-header-re "\\|"
-                                 doctest-results-divider-re) nil t)
-      (let ((result (match-string 0)))
-        (if (string-match doctest-results-header-re result)
-            result
-          nil))
-    nil))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; mmm-mode support
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; MMM Mode is a minor mode for Emacs which allows Multiple Major
-;; Modes to coexist in a single buffer.  
-
-;;;###autoload
-(defun doctest-register-mmm-classes (&optional add-mode-ext-classes
-                                               fix-mmm-fontify-region-bug)
-  "Register doctest's mmm classes, allowing doctest to be used as a
-submode region in other major modes, such as python-mode and rst-mode.
-Two classes are registered:
-
-`doctest-docstring'
-
-    Used to edit docstrings containing doctest examples in python-
-    mode.  Docstring submode regions start and end with triple-quoted
-    strings (\"\"\").  In order to avoid confusing start-string
-    markers and end-string markers, all triple-quote strings in the
-    buffer are treated as submode regions (even if they're not
-    actually docstrings).  Use (C-c % C-d) to insert a new doctest-
-    docstring region.  When `doctest-execute' (C-c C-c) is called
-    inside a doctest-docstring region, it executes just the current
-    docstring.  The globals for this execution are constructed by
-    importing the current buffer's contents in Python.
-
-`doctest-example'
-
-    Used to edit doctest examples in text-editing modes, such as
-    `rst-mode' or `text-mode'.  Docstring submode regions start with
-    optionally indented prompts (>>>) and end with blank lines.  Use
-    (C-c % C-e) to insert a new doctest-example region.  When
-    `doctest-execute' (C-c C-c) is called inside a doctest-example
-    region, it executes all examples in the buffer.
-
-If ADD-MODE-EXT-CLASSES is true, then register the new classes in
-`mmm-mode-ext-classes-alist', which will cause them to be used by
-default in the following modes:
-
-    doctest-docstring:  python-mode
-    doctest-example:    rst-mode
-
-If FIX-MMM-FONTIFY-REGION-BUG is true, then register a hook that will
-fix a bug in `mmm-fontify-region' that affects some (but not all)
-versions of emacs.  (See `doctest-fixed-mmm-fontify-region' for more
-info.)"
-  (interactive)
-  (require 'mmm-auto)
-  (mmm-add-classes
-   '(
-     ;; === doctest-docstring ===
-     (doctest-docstring :submode doctest-mode
-      
-      ;; The front is any triple-quote.  Include it in the submode region,
-      ;; to prevent clashes between the two syntax tables over quotes.
-      :front "\\(\"\"\"\\|'''\\)" :include-front t
-      
-      ;; The back matches the front.  Include just the first character
-      ;; of the quote.  If we didn't include at least one quote, then
-      ;; the outer modes quote-counting would be thrown off.  But if
-      ;; we include all three, we run into a bug in mmm-mode.  See
-      ;; <http://tinyurl.com/2fa83w> for more info about the bug.
-      :save-matches t :back "~1" :back-offset 1 :end-not-begin t
-      
-      ;; Define a skeleton for entering new docstrings.
-      :insert ((?d docstring nil @ "\"\"" @ "\"" \n
-                   _ \n "\"" @ "\"\"" @)))
-     
-     ;; === doctest-example ===
-     (doctest-example
-      :submode doctest-mode
-      ;; The front is an optionally indented prompt.
-      :front "^[ \t]*>>>" :include-front t
-      ;; The back is a blank line.
-      :back "^[ \t]*$"
-      ;; Define a skeleton for entering new docstrings.
-      :insert ((?e doctest-example nil
-                   @ @ "    >>> " _ "\n\n" @ @)))))
-  
-  ;; Register some local variables that need to be saved.
-  (add-to-list 'mmm-save-local-variables
-               '(doctest-results-buffer buffer))
-  (add-to-list 'mmm-save-local-variables
-               '(doctest-example-markers buffer))
-
-  ;; Register association with modes, if requested.
-  (when add-mode-ext-classes
-    (mmm-add-mode-ext-class 'python-mode nil 'doctest-docstring)
-    (mmm-add-mode-ext-class 'rst-mode nil 'doctest-example))
-
-  ;; Fix the buggy mmm-fontify-region, if requested.
-  (when fix-mmm-fontify-region-bug
-    (add-hook 'mmm-mode-hook 'doctest-fix-mmm-fontify-region-bug)))
-
-(defvar doctest-old-mmm-fontify-region 'nil
-  "Used to hold the original definition of `mmm-fontify-region' when it
-is rebound by `doctest-fix-mmm-fontify-region-bug'.")
-
-(defun doctest-fix-mmm-fontify-region-bug ()
-  "A function for `mmm-mode-hook' which fixes a potential bug in
-`mmm-fontify-region' by using `doctest-fixed-mmm-fontify-region'
-instead.  (See `doctest-fixed-mmm-fontify-region' for more info.)"
-  (setq font-lock-fontify-region-function
-        'doctest-fixed-mmm-fontify-region))
-
-(defun doctest-fixed-mmm-fontify-region (start stop &optional loudly)
-  "A replacement for `mmm-fontify-region', which fixes a bug caused by
-versions of emacs where post-command-hooks are run *before*
-fontification.  `mmm-mode' assumes that its post-command-hook will be
-run after fontification; and if it's not, then mmm-mode can end up
-with the wrong local variables, keymap, etc. after fontification.  We
-fix that here by redefining `mmm-fontify-region' to remember what
-submode overlay it started in; and to return to that overlay after
-fontification is complete.  The original definition of
-`mmm-fontify-region' is stored in `doctest-old-mmm-fontify-region'."
-  (let ((overlay mmm-current-overlay))
-    (mmm-fontify-region start stop loudly)
-    (if (and overlay (or (< (point) (overlay-start overlay))
-                         (> (point) (overlay-end overlay))))
-        (goto-char (overlay-start overlay)))
-    (mmm-update-submode-region)))
-
-(defun doctest-in-mmm-docstring-overlay ()
-  (and (featurep 'mmm-auto)
-       (mmm-overlay-at (point))
-       (save-excursion
-         (goto-char (overlay-start (mmm-overlay-at (point))))
-         (looking-at "\"\"\"\\|\'\'\'"))))
-
-(defun doctest-narrow-to-mmm-overlay ()
-  "If we're in an mmm-mode overlay, then narrow to that overlay.
-This is useful, e.g., to keep from interpreting the close-quote of a
-docstring as part of the example's output."
-  (let ((bounds (doctest-mmm-overlay-bounds)))
-    (when bounds (narrow-to-region (car bounds) (cdr bounds)))))
-
-(defun doctest-default-margin-in-mmm-docstring-overlay ()
-  (save-excursion
-    (let ((pos (car (doctest-mmm-overlay-bounds))))
-      (goto-char pos)
-      (when (doctest-looking-back "\"\"\"\\|\'\'\'")
-        (setq pos (- pos 3)))
-      (beginning-of-line)
-      (- pos (point)))))
-
-(defun doctest-mmm-overlay-bounds ()
-  (when (featurep 'mmm-auto)
-    (let ((overlay (mmm-overlay-at (point))))
-      (when overlay
-        (let ((start (overlay-start overlay))
-              (end (overlay-end overlay)))
-          (when (doctest-in-mmm-docstring-overlay)
-            (save-excursion
-              (goto-char start)
-              (re-search-forward "[\"\']*")
-              (setq start (point))
-              (goto-char end)
-              (while (doctest-looking-back "[\"\']")
-                (backward-char 1))
-              (setq end (point))))
-          (cons start end))))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Helper functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun doctest-on-source-line-p (&optional prompt)
-  "Return true if the current line is a source line.  The optional
-argument prompt can be used to specify which type of source
-line (... or >>>)."
-  (save-excursion
-    (beginning-of-line)
-    ;; Check if we're looking at a prompt (of the right type).
-    (when (and (looking-at doctest-prompt-re)
-               (or (null prompt)
-                   (equal prompt (substring (match-string 2) 0 3))))
-      ;; Scan backwards to make sure there's a >>> somewhere.  Otherwise,
-      ;; this might be a '...' in the text or in an example's output.
-      (while (looking-at "^[ \t]*[.][.][.]")
-        (forward-line -1))
-      (looking-at "^[ \t]*>>>"))))
-
-(defun doctest-on-empty-source-line-p ()
-  "Return true if the current line contains a bare prompt."
-  (save-excursion
-    (beginning-of-line)
-    (and (doctest-on-source-line-p)
-         (looking-at (concat doctest-prompt-re "$")))))
-
-(defun doctest-on-output-line-p ()
-  "Return true if the current line is an output line."
-  (save-excursion
-    (beginning-of-line)
-    ;; The line must not be blank or a source line.
-    (when (not (or (doctest-on-source-line-p) (looking-at "[ \t]*$")))
-      ;; The line must follow a source line, with no intervening blank
-      ;; lines.
-      (while (not (or (doctest-on-source-line-p) (looking-at "[ \t]*$")
-                      (= (point) (point-min))))
-        (forward-line -1))
-      (doctest-on-source-line-p))))
-
-(defun doctest-find-output-line (&optional limit)
-  "Move forward to the next doctest output line (staying within
-the given bounds).  Return the character position of the doctest
-output line if one was found, and false otherwise."
-  (let ((found-it nil) ; point where we found an output line
-	(limit (or limit (point-max)))) ; default value for limit
-    (save-excursion
-      ;; Keep moving forward, one line at a time, until we find a
-      ;; doctest output line.
-      (while (and (not found-it) (< (point) limit) (not (eobp)))
-	(if (and (not (eolp)) (doctest-on-output-line-p))
-	    (setq found-it (point))
-	  (forward-line))))
-    ;; If we found a doctest output line, then go to it.
-    (if found-it (goto-char found-it))))
-
-(defun doctest-line-indentation ()
-  "Helper for doctest-replace-output: return the whitespace indentation
-at the beginning of this line."
-  (save-excursion
-    (end-of-line)
-    (re-search-backward "^\\( *\\)" nil t)
-    (match-string 1)))
-
-(defun doctest-optionflags (&optional diff)
-  "Return a string describing the optionflags that should be used
-by doctest.  If DIFF is non-nil, then add the REPORT_UDIFF flag."
-  (let ((flags "0"))
-    (dolist (flag doctest-optionflags)
-      (setq flags (concat flags "|" flag)))
-    (if diff (concat flags "|" "REPORT_UDIFF") flags)))
-  
-(defun doctest-results-loc-re ()
-  "Return the regexp that should be used to look for doctest example
-location markers in doctest's output (based on which version of
-doctest was used"
-  (cond
-   ((equal doctest-results-py-version 'py21)
-    doctest-py21-results-loc-re)
-   ((equal doctest-results-py-version 'py24)
-    doctest-py24-results-loc-re)
-   (t (error "bad value for doctest-results-py-version"))))
-
-(defun doctest-results-buffer-name ()
-  "Return the buffer name that should be used for the doctest results
-buffer.  This is computed from the variable
-`doctest-results-buffer-name'."
-  (doctest-replace-regexp-in-string
-   "%[nfN]"
-   (lambda (sym)
-     (cond ((equal sym "%n") (buffer-name))
-           ((equal sym "%N") (doctest-replace-regexp-in-string
-                              "[.]doctest$" "" (buffer-name) t))
-           ((equal sym "%f") (buffer-file-name))))
-   doctest-results-buffer-name t))
-
-(defun doctest-script (input-file globs-file diff)
-  "..."
-  (doctest-replace-regexp-in-string
-   "%[tnflm]"
-   (lambda (sym)
-     (cond ((equal sym "%n") (buffer-name))
-           ((equal sym "%f") (buffer-file-name))
-           ((equal sym "%l") (doctest-optionflags diff))
-           ((equal sym "%t") input-file)
-           ((equal sym "%m") (or globs-file ""))))
-   doctest-script t))
-
-(defun doctest-hide-example-source ()
-  "Delete the source code listings from the results buffer (since it's
-easy enough to see them in the original buffer)"
-  (save-excursion
-    (set-buffer doctest-results-buffer)
-    (toggle-read-only 0)
-    (goto-char (point-min))
-    (while (re-search-forward doctest-example-source-re nil t)
-      (replace-match "" nil nil))
-    (toggle-read-only t)))
-
-(defun doctest-results-buffer-valid-p ()
-  "Return true if this buffer has a live results buffer; and that
-results buffer reports this buffer as its source buffer.  (Two
-buffers in doctest-mode might point to the same results buffer;
-but only one of them will be equal to that results buffer's
-source buffer."
-  (let ((cur-buf (current-buffer)))
-    (and (buffer-live-p doctest-results-buffer)
-         (save-excursion
-           (set-buffer doctest-results-buffer)
-           (equal cur-buf doctest-source-buffer)))))
-
-(defun doctest-update-mode-line (value)
-  "Update the doctest mode line with the given string value.  This
-is used to display information about asynchronous processes that
-are run by doctest-mode."
-  (setq doctest-mode-line-process
-        value)
-  (force-mode-line-update t))
-
-(defun doctest-version ()
-  "Echo the current version of `doctest-mode' in the minibuffer."
-  (interactive)
-  (message "Using `doctest-mode' version %s" doctest-version))
-
-(defun doctest-warn (msg &rest args)
-  "Display a doctest warning message."
-  (if (fboundp 'display-warning)
-      (display-warning 'doctest (apply 'format msg args))
-    (apply 'message msg args)))
-
-(defun doctest-debug (msg &rest args)
-  "Display a doctest debug message."
-  (if (fboundp 'display-warning)
-      (display-warning 'doctest (apply 'format msg args) 'debug)
-    (apply 'message msg args)))
-
-(defvar doctest-serial-number 0) ;used if broken-temp-names.
-(defun doctest-temp-name ()
-  "Return a new temporary filename, for use in calling doctest."
-  (if (memq 'broken-temp-names features)
-      (let
-	  ((sn doctest-serial-number)
-	   (pid (and (fboundp 'emacs-pid) (emacs-pid))))
-	(setq doctest-serial-number (1+ doctest-serial-number))
-	(if pid
-	    (format "doctest-%d-%d" sn pid)
-	  (format "doctest-%d" sn)))
-    (make-temp-name "doctest-")))
-
-(defun doctest-fontify-line (charpos)
-  "Run font-lock-fontify-region on the line containing the given
-position."
-  (if (and charpos (functionp 'font-lock-fontify-region))
-      (save-excursion
-        (goto-char charpos)
-        (let ((beg (progn (beginning-of-line) (point)))
-              (end (progn (end-of-line) (point))))
-          (font-lock-fontify-region beg end)))))
-
-(defun doctest-do-auto-fill ()
-  "If the current line is a soucre line or an output line, do nothing.
-Otherwise, call (do-auto-fill)."
-  (cond
-   ;; Don't wrap source lines.
-   ((doctest-on-source-line-p) nil)
-   ;; Don't wrap output lines
-   ((doctest-on-output-line-p) nil)
-   ;; Wrap all other lines
-   (t (do-auto-fill))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Emacs Compatibility Functions
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Define compatible versions of functions that are defined
-;; for some versions of emacs but not others.
-
-;; Backwards compatibility: looking-back
-(cond ((fboundp 'looking-back) ;; Emacs 22.x
-       (defalias 'doctest-looking-back 'looking-back))
-      (t
-       (defun doctest-looking-back (regexp)
-         "Return true if text before point matches REGEXP."
-         (save-excursion
-           (let ((orig-pos (point)))
-             ;; Search backwards for the regexp.
-             (if (re-search-backward regexp nil t)
-                 ;; Check if it ends at the original point.
-                 (= orig-pos (match-end 0))))))))
-
-;; Backwards compatibility: replace-regexp-in-string
-(cond ((fboundp 'replace-regexp-in-string)
-       (defalias 'doctest-replace-regexp-in-string 'replace-regexp-in-string))
-      (t ;; XEmacs 21.x or Emacs 20.x
-       (defun doctest-replace-regexp-in-string
-         (regexp rep string &optional fixedcase literal)
-         "Replace all matches for REGEXP with REP in STRING."
-         (let ((start 0))
-           (while (and (< start (length string))
-                       (string-match regexp string start))
-             (setq start (+ (match-end 0) 1))
-             (let ((newtext (if (functionp rep)
-                                (save-match-data
-                                  (funcall rep (match-string 0 string)))
-                              rep)))
-               (setq string (replace-match newtext fixedcase
-                                           literal string)))))
-         string)))
-
-;; Backwards compatibility: line-number
-(cond ((fboundp 'line-number) ;; XEmacs
-       (defalias 'doctest-line-number 'line-number))
-      ((fboundp 'line-number-at-pos) ;; Emacs 22.x
-       (defalias 'doctest-line-number 'line-number-at-pos))
-      (t ;; Emacs 21.x
-       (defun doctest-line-number (&optional pos)
-         "Return the line number of POS (default=point)."
-         (1+ (count-lines 1
-               (save-excursion (progn (beginning-of-line)
-                                      (or pos (point)))))))))
-
-;; Backwards compatibility: process-live-p
-(cond ((fboundp 'process-live-p) ;; XEmacs
-       (defalias 'doctest-process-live-p 'process-live-p))
-      (t ;; Emacs
-       (defun doctest-process-live-p (process)
-         (and (processp process)
-              (equal (process-status process) 'run)))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Doctest Results Mode (output of doctest-execute-buffer)
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Register the font-lock keywords (xemacs)
-(put 'doctest-results-mode 'font-lock-defaults 
-     '(doctest-results-font-lock-keywords))
-
-;; Register the font-lock keywords (older versions of gnu emacs)
-(when (boundp 'font-lock-defaults-alist)
-  (add-to-list 'font-lock-defaults-alist
-               '(doctest-results-mode doctest-results-font-lock-keywords 
-                                      nil nil nil nil)))
-
-(defvar doctest-selected-failure nil
-  "The location of the currently selected failure.
-This variable is uffer-local to doctest-results-mode buffers.")
-
-(defvar doctest-source-buffer nil
-  "The buffer that spawned this one.
-This variable is uffer-local to doctest-results-mode buffers.")
-
-(defvar doctest-results-py-version nil
-  "A symbol indicating which version of Python was used to generate
-the results in a doctest-results-mode buffer.  Can be either the
-symbol `py21' or the symbol `py24'.
-This variable is uffer-local to doctest-results-mode buffers.")
-
-;; Keymap for doctest-results-mode.
-(defconst doctest-results-mode-map 
-  (let ((map (make-keymap)))
-    (define-key map [return] 'doctest-select-failure)
-    map) 
-  "Keymap for doctest-results-mode.")
-
-;; Syntax table for doctest-results-mode.
-(defvar doctest-results-mode-syntax-table nil
-  "Syntax table used in `doctest-results-mode' buffers.")
-(when (not doctest-results-mode-syntax-table)
-  (setq doctest-results-mode-syntax-table (make-syntax-table))
-  (dolist (entry '(("(" . "()") ("[" . "(]") ("{" . "(}")
-                   (")" . ")(") ("]" . ")[") ("}" . "){")
-                   ("$%&*+-/<=>|'\"`" . ".") ("_" . "w")))
-    (dolist (char (string-to-list (car entry)))
-      (modify-syntax-entry char (cdr entry)
-                           doctest-results-mode-syntax-table))))
-
-;; Define the mode
-(defun doctest-results-mode ()
-  "A major mode used to display the results of running doctest.
-See `doctest-mode'.
-
-\\{doctest-results-mode-map}"
-  (interactive)
-  
-  ;; Declare local variables.
-  (kill-all-local-variables)
-  (make-local-variable 'font-lock-defaults)
-  (make-local-variable 'doctest-selected-failure)
-  (make-local-variable 'doctest-source-buffer)
-  (make-local-variable 'doctest-results-py-version)
-  
-  ;; Define local variables.
-  (setq major-mode              'doctest-results-mode
-	mode-name               "Doctest-Results"
-        mode-line-process       'doctest-mode-line-process
-        font-lock-defaults      '(doctest-results-font-lock-keywords
-                                  nil nil nil nil))
-  ;; Define keymap.
-  (use-local-map doctest-results-mode-map)
-  
-  ;; Define the syntax table.
-  (set-syntax-table doctest-results-mode-syntax-table)
-  
-  ;; Enable font-lock mode.
-  (if (featurep 'font-lock) (font-lock-mode 1)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Doctest Mode
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; Register the font-lock keywords (xemacs)
-(put 'doctest-mode 'font-lock-defaults '(doctest-font-lock-keywords
-                                         nil nil nil nil))
-
-;; Register the font-lock keywords (older versions of gnu emacs)
-(when (boundp 'font-lock-defaults-alist)
-  (add-to-list 'font-lock-defaults-alist
-               '(doctest-mode doctest-font-lock-keywords
-                              nil nil nil nil)))
-  
-(defvar doctest-results-buffer nil
-  "The output buffer for doctest-mode.
-This variable is buffer-local to doctest-mode buffers.")
-
-(defvar doctest-example-markers nil
-  "A list mapping markers to the line numbers at which they appeared
-in the buffer at the time doctest was last run.  This is used to find
-'original' line numbers, which can be used to search the doctest
-output buffer.  It's encoded as a list of (MARKER . POS) tuples, in
-reverse POS order.
-This variable is buffer-local to doctest-mode buffers.")
-
-;; These are global, since we only one run process at a time:
-(defvar doctest-async-process nil
-  "The process object created by the asynchronous doctest process")
-(defvar doctest-async-process-tempfiles nil
-  "A list of tempfile names created by the asynchronous doctest process")
-(defvar doctest-async-process-buffer nil
-  "The source buffer for the asynchronous doctest process")
-(defvar doctest-mode-line-process ""
-  "A string displayed on the modeline, to indicate when doctest is
-running asynchronously.")
-
-;; Keymap for doctest-mode.  n.b.: we intentionally define [tab]
-;; rather than overriding indent-line-function, since we don't want
-;; doctest-indent-source-line to be called by do-auto-fill.
-(defconst doctest-mode-map 
-  (let ((map (make-keymap)))
-    (define-key map [backspace] 'doctest-electric-backspace)
-    (define-key map [return] 'doctest-newline-and-indent)
-    (define-key map [tab] 'doctest-indent-source-line)
-    (define-key map ":" 'doctest-electric-colon)
-    (define-key map "\C-c\C-v" 'doctest-version)
-    (define-key map "\C-c\C-c" 'doctest-execute)
-    (define-key map "\C-c\C-d" 'doctest-execute-with-diff)
-    (define-key map "\C-c\C-n" 'doctest-next-failure)
-    (define-key map "\C-c\C-p" 'doctest-prev-failure)
-    (define-key map "\C-c\C-a" 'doctest-first-failure)
-    (define-key map "\C-c\C-e" 'doctest-last-failure)
-    (define-key map "\C-c\C-z" 'doctest-last-failure)
-    (define-key map "\C-c\C-r" 'doctest-replace-output)
-    (define-key map "\C-c|" 'doctest-execute-region)
-    map) 
-  "Keymap for doctest-mode.")
-
-;; Syntax table for doctest-mode.
-(defvar doctest-mode-syntax-table nil
-  "Syntax table used in `doctest-mode' buffers.")
-(when (not doctest-mode-syntax-table)
-  (setq doctest-mode-syntax-table (make-syntax-table))
-  (dolist (entry '(("(" . "()") ("[" . "(]") ("{" . "(}")
-                   (")" . ")(") ("]" . ")[") ("}" . "){")
-                   ("$%&*+-/<=>|'\"`" . ".") ("_" . "w")))
-    (dolist (char (string-to-list (car entry)))
-      (modify-syntax-entry char (cdr entry) doctest-mode-syntax-table))))
-
-;; Use doctest mode for files ending in .doctest
-;;;###autoload
-(add-to-list 'auto-mode-alist '("\\.doctest$" . doctest-mode))
-
-;;;###autoload
-(defun doctest-mode ()
-  "A major mode for editing text files that contain Python
-doctest examples.  Doctest is a testing framework for Python that
-emulates an interactive session, and checks the result of each
-command.  For more information, see the Python library reference:
-<http://docs.python.org/lib/module-doctest.html>
-
-`doctest-mode' defines three kinds of line, each of which is
-treated differently:
-
-  - 'Source lines' are lines consisting of a Python prompt
-    ('>>>' or '...'), followed by source code.  Source lines are
-    colored (similarly to `python-mode') and auto-indented.
-
-  - 'Output lines' are non-blank lines immediately following
-    source lines.  They are colored using several doctest-
-    specific output faces.
-
-  - 'Text lines' are any other lines.  They are not processed in
-    any special way.
-
-\\{doctest-mode-map}"
-  (interactive)
-  
-  ;; Declare local variables.
-  (kill-all-local-variables)
-  (make-local-variable 'font-lock-defaults)
-  (make-local-variable 'doctest-results-buffer)
-  (make-local-variable 'doctest-example-markers)
-  
-  ;; Define local variables.
-  (setq major-mode              'doctest-mode
-        mode-name               "Doctest"
-        mode-line-process       'doctest-mode-line-process
-        font-lock-defaults      '(doctest-font-lock-keywords
-                                  nil nil nil nil))
-  
-  ;; Define keymap.
-  (use-local-map doctest-mode-map)
-
-  ;; Define the syntax table.
-  (set-syntax-table doctest-mode-syntax-table)
-  
-  ;; Enable auto-fill mode.
-  (auto-fill-mode 1)
-  (setq auto-fill-function 'doctest-do-auto-fill)
-
-  ;; Enable font-lock mode.
-  (if (featurep 'font-lock) (font-lock-mode 1))
-
-  ;; Run the mode hook.
-  (run-hooks 'doctest-mode-hook))
-
-(provide 'doctest-mode)
-;;; doctest-mode.el ends here
deleted file mode 100644
--- a/.elisp/http-twiddle.el
+++ /dev/null
@@ -1,153 +0,0 @@
-;;; http-twiddle.el -- send & twiddle & resend HTTP requests
-;;
-;; Version 1.0 written by Luke Gorrie <luke@synap.se> in February 2006
-;; This program belongs to the public domain.
-;;
-;; (downloaded from http://fresh.homeunix.net/~luke/misc/emacs/http-twiddle.el)
-;;
-;; This is a program for testing hand-written HTTP requests. You write
-;; your request in an Emacs buffer (using http-twiddle-mode) and then
-;; press `C-c C-c' each time you want to try sending it to the server.
-;; This way you can interactively debug the requests. To change port or
-;; destination do `C-u C-c C-c'.
-;;
-;; The program is particularly intended for the POST-"500 internal
-;; server error"-edit-POST loop of integration with SOAP programs.
-;;
-;; The mode is activated by `M-x http-twiddle-mode' or automatically
-;; when opening a filename ending with .http-twiddle.
-;;
-;; The request can either be written from scratch or you can paste it
-;; from a snoop/tcpdump and then twiddle from there.
-;;
-;; See the documentation for the `http-twiddle-mode' and
-;; `http-twiddle-mode-send' functions below for more details and try
-;; `M-x http-twiddle-mode-demo' for a simple get-started example.
-;;
-;; Tested with GNU Emacs 21.4.1 and not tested/ported on XEmacs yet.
-
-;;; Example buffer:
-
-;; POST / HTTP/1.0
-;; Connection: close
-;; Content-Length: $Content-Length
-;;
-;; The request body goes here
-
-(require 'font-lock)                    ; faces
-
-(eval-when-compile
-  (unless (fboundp 'define-minor-mode)
-    (require 'easy-mmode)
-    (defalias 'define-minor-mode 'easy-mmode-define-minor-mode))
-  (require 'cl))
-
-(define-minor-mode http-twiddle-mode
-  "Major mode for twiddling around with HTTP requests and sending them.
-Use `http-twiddle-mode-send' (\\[http-twiddle-mode-send]) to send the request."
-  nil
-  " http-twiddle"
-  '(("\C-c\C-c" . http-twiddle-mode-send)))
-
-(defvar http-twiddle-show-request t
-  "*Show the request in the transcript.")
-
-(add-to-list 'auto-mode-alist '("\\.http-twiddle$" . http-twiddle-mode))
-
-(defvar http-twiddle-endpoint nil
-  "Cache of the (HOST PORT) to send the request to.")
-
-(defvar http-twiddle-process nil
-  "Socket connected to the webserver.")
-
-(defvar http-twiddle-port-history '()
-  "History of port arguments entered in the minibuffer.
-\(To make XEmacs happy.)")
-
-(defvar http-twiddle-host-history '()
-  "History of port arguments entered in the minibuffer.
-\(To make XEmacs happy.)")
-
-(defun http-twiddle-mode-send (host port)
-  "Send the current buffer to the server.
-Linebreaks are automatically converted to CRLF (\\r\\n) format and any
-occurences of \"$Content-Length\" are replaced with the actual content
-length."
-  (interactive (http-twiddle-read-endpoint))
-  ;; close any old connection
-  (when http-twiddle-process
-    (kill-buffer (process-buffer http-twiddle-process)))
-  (let ((content (buffer-string)))
-    (with-temp-buffer
-      (insert content)
-      (http-twiddle-convert-cr-to-crlf)
-      (http-twiddle-expand-content-length)
-      (let ((request (buffer-string)))
-        (setq http-twiddle-process
-              (open-network-stream "http-twiddle" "*HTTP Twiddle*" host port))
-        (set-process-filter http-twiddle-process 'http-twiddle-process-filter)
-        (set-process-sentinel http-twiddle-process 'http-twiddle-process-sentinel)
-        (process-send-string http-twiddle-process request)
-        (save-selected-window
-          (pop-to-buffer (process-buffer http-twiddle-process))
-          (when http-twiddle-show-request
-            (insert request)
-            (set-window-start (selected-window) (point))
-            (add-text-properties (point-min) (point-max)
-                                 '(face font-lock-comment-face)))
-          (set-mark (point)))))))
-
-(defun http-twiddle-read-endpoint ()
-  "Return the endpoint (HOST PORT) to send the request to."
-  (if (and http-twiddle-endpoint (null current-prefix-arg))
-      http-twiddle-endpoint
-    (setq http-twiddle-endpoint
-          (list (read-string "Host: (default localhost) "
-                             nil 'http-twiddle-host-history "localhost")
-                (let ((input (read-from-minibuffer "Port: " nil nil t 'http-twiddle-port-history)))
-                  (if (integerp input)
-                      input
-                    (error "Not an integer: %S" input)))))))
-
-(defun http-twiddle-convert-cr-to-crlf ()
-  "Convert \\n linebreaks to \\r\\n in the whole buffer."
-  (save-excursion
-    (goto-char (point-min))
-    (while (re-search-forward "[^\r]\n" nil t)
-      (backward-char)
-      (insert "\r"))))
-
-(defun http-twiddle-expand-content-length ()
-  "Replace any occurences of $Content-Length with the actual Content-Length."
-  (save-excursion
-    (goto-char (point-min))
-    (let ((content-length
-           (save-excursion (when (search-forward "\r\n\r\n" nil t)
-                             (- (point-max) (point))))))
-      (unless (null content-length)
-        (let ((case-fold-search t))
-          (while (search-forward "$content-length" nil t)
-            (replace-match (format "%d" content-length) nil t)))))))
-
-(defun http-twiddle-process-filter (process string)
-  "Process data from the socket by inserting it at the end of the buffer."
-  (with-current-buffer (process-buffer process)
-    (goto-char (point-max))
-    (insert string)))
-
-(defun http-twiddle-process-sentinel (process what)
-  (with-current-buffer (process-buffer process)
-    (goto-char (point-max))
-    (let ((start (point)))
-      (insert "Connection closed\n")
-      (add-text-properties start (point) '(face font-lock-string-face)))))
-
-(defun http-twiddle-mode-demo ()
-  (interactive)
-  (pop-to-buffer (get-buffer-create "*http-twiddle demo*"))
-  (http-twiddle-mode 1)
-  (erase-buffer)
-  (insert "POST / HTTP/1.0\nContent-Length: $Content-Length\nConnection: close\n\nThis is the POST body.\n")
-  (message "Now press `C-c C-c' and enter a webserver address (e.g. google.com port 80)."))
-
-(provide 'http-twiddle)
deleted file mode 100644
--- a/.elisp/ipython.el
+++ /dev/null
@@ -1,483 +0,0 @@
-;;; ipython.el --- Adds support for IPython to python-mode.el
-
-;; Copyright (C) 2002, 2003, 2004, 2005 Alexander Schmolck
-;; Author:        Alexander Schmolck
-;; Keywords:      ipython python languages oop
-;; URL:           http://ipython.scipy.org
-;; Compatibility: Emacs21, XEmacs21
-;; FIXME: #$@! INPUT RING
-(defconst ipython-version "$Revision: 2275 $"
-  "VC version number.")
-
-;;; Commentary 
-;; This library makes all the functionality python-mode has when running with
-;; the normal python-interpreter available for ipython, too. It also enables a
-;; persistent py-shell command history across sessions (if you exit python
-;; with C-d in py-shell) and defines the command `ipython-to-doctest', which
-;; can be used to convert bits of a ipython session into something that can be
-;; used for doctests. To install, put this file somewhere in your emacs
-;; `load-path' [1] and add the following line to your ~/.emacs file (the first
-;; line only needed if the default (``"ipython"``) is wrong)::
-;;
-;;   (setq ipython-command "/SOME-PATH/ipython")
-;;   (require 'ipython)
-;;
-;; Ipython will be set as the default python shell, but only if the ipython
-;; executable is in the path. For ipython sessions autocompletion with <tab>
-;; is also enabled (experimental feature!). Please also note that all the
-;; terminal functions in py-shell are handled by emacs's comint, **not** by
-;; (i)python, so importing readline etc. will have 0 effect.
-;;
-;; To start an interactive ipython session run `py-shell' with ``M-x py-shell``
-;; (or the default keybinding ``C-c C-!``).
-;;
-;; NOTE: This mode is currently somewhat alpha and although I hope that it
-;; will work fine for most cases, doing certain things (like the
-;; autocompletion and a decent scheme to switch between python interpreters)
-;; properly will also require changes to ipython that will likely have to wait
-;; for a larger rewrite scheduled some time in the future.
-;; 
-;; Also note that you currently NEED THE CVS VERSION OF PYTHON.EL.
-;;
-;; Further note that I don't know whether this runs under windows or not and
-;; that if it doesn't I can't really help much, not being afflicted myself.
-;;
-;;
-;; Hints for effective usage
-;; -------------------------
-;;
-;; - IMO the best feature by far of the ipython/emacs combo is how much easier it
-;;   makes it to find and fix bugs thanks to the ``%pdb on``/ pdbtrack combo. Try
-;;   it: first in the ipython to shell do ``%pdb on`` then do something that will
-;;   raise an exception (FIXME nice example) -- and be amazed how easy it is to
-;;   inspect the live objects in each stack frames and to jump to the
-;;   corresponding sourcecode locations as you walk up and down the stack trace
-;;   (even without ``%pdb on`` you can always use ``C-c -`` (`py-up-exception')
-;;   to jump to the corresponding source code locations).
-;;
-;; - emacs gives you much more powerful commandline editing and output searching
-;;   capabilities than ipython-standalone -- isearch is your friend if you
-;;   quickly want to print 'DEBUG ...' to stdout out etc.
-;;
-;; - This is not really specific to ipython, but for more convenient history
-;;   access you might want to add something like the following to *the beggining*
-;;   of your ``.emacs`` (if you want behavior that's more similar to stand-alone
-;;   ipython, you can change ``meta p`` etc. for ``control p``)::
-;;
-;;         (require 'comint)
-;;         (define-key comint-mode-map [(meta p)] 
-;;           'comint-previous-matching-input-from-input)
-;;         (define-key comint-mode-map [(meta n)] 
-;;           'comint-next-matching-input-from-input)
-;;         (define-key comint-mode-map [(control meta n)]
-;;            'comint-next-input)
-;;         (define-key comint-mode-map [(control meta p)]
-;;            'comint-previous-input)
-;;
-;; - Be aware that if you customize py-python-command previously, this value
-;;   will override what ipython.el does (because loading the customization
-;;   variables comes later).
-;;
-;; Please send comments and feedback to the ipython-list
-;; (<ipython-user@scipy.net>) where I (a.s.) or someone else will try to
-;; answer them (it helps if you specify your emacs version, OS etc; 
-;; familiarity with <http://www.catb.org/~esr/faqs/smart-questions.html> might
-;; speed up things further).
-;;
-;; Footnotes:
-;;
-;;     [1] If you don't know what `load-path' is, C-h v load-path will tell
-;;     you; if required you can also add a new directory. So assuming that
-;;     ipython.el resides in ~/el/, put this in your emacs:
-;;
-;;
-;;           (add-to-list 'load-path "~/el")
-;;           (setq ipython-command "/some-path/ipython")
-;;           (require 'ipython)
-;;
-;;
-;;
-;;
-;; TODO:
-;;      - do autocompletion properly
-;;      - implement a proper switching between python interpreters
-;;
-;; BUGS:
-;;      - neither::
-;;
-;;         (py-shell "-c print 'FOOBAR'")
-;;       
-;;        nor::
-;;       
-;;         (let ((py-python-command-args (append py-python-command-args 
-;;                                              '("-c" "print 'FOOBAR'"))))
-;;           (py-shell))
-;;
-;;        seem to print anything as they should
-;;
-;;      - look into init priority issues with `py-python-command' (if it's set
-;;        via custom)
-
-
-;;; Code
-(require 'cl)
-(require 'shell)
-(require 'executable)
-(require 'ansi-color)
-
-(defcustom ipython-command "ipython"
-  "*Shell command used to start ipython."
-  :type 'string 
-  :group 'python)
-
-;; Users can set this to nil
-(defvar py-shell-initial-switch-buffers t
-  "If nil, don't switch to the *Python* buffer on the first call to
-  `py-shell'.")
-
-(defvar ipython-backup-of-py-python-command nil
-  "HACK")
-
-  
-(defvar ipython-de-input-prompt-regexp "\\(?:
-In \\[[0-9]+\\]: *.*
-----+> \\(.*
-\\)[\n]?\\)\\|\\(?:
-In \\[[0-9]+\\]: *\\(.*
-\\)\\)\\|^[ ]\\{3\\}[.]\\{3,\\}: *\\(.*
-\\)"
-  "A regular expression to match the IPython input prompt and the python
-command after it. The first match group is for a command that is rewritten,
-the second for a 'normal' command, and the third for a multiline command.")
-(defvar ipython-de-output-prompt-regexp "^Out\\[[0-9]+\\]: "
-  "A regular expression to match the output prompt of IPython.")
-
-
-(if (not (executable-find ipython-command))
-    (message (format "Can't find executable %s - ipython.el *NOT* activated!!!"
-                     ipython-command))
-    ;; XXX load python-mode, so that we can screw around with its variables
-    ;; this has the disadvantage that python-mode is loaded even if no
-    ;; python-file is ever edited etc. but it means that `py-shell' works
-    ;; without loading a python-file first. Obviously screwing around with
-    ;; python-mode's variables like this is a mess, but well.
-    (require 'python-mode)
-    ;; turn on ansi colors for ipython and activate completion
-    (defun ipython-shell-hook ()
-      ;; the following is to synchronize dir-changes
-      (make-local-variable 'shell-dirstack)
-      (setq shell-dirstack nil)
-      (make-local-variable 'shell-last-dir)
-      (setq shell-last-dir nil)
-      (make-local-variable 'shell-dirtrackp)
-      (setq shell-dirtrackp t)
-      (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
-
-      (ansi-color-for-comint-mode-on)
-      (define-key py-shell-map [tab] 'ipython-complete)
-      ;; Add this so that tab-completion works both in X11 frames and inside
-      ;; terminals (such as when emacs is called with -nw).
-      (define-key py-shell-map "\t" 'ipython-complete)
-      ;;XXX this is really just a cheap hack, it only completes symbols in the
-      ;;interactive session -- useful nonetheless.
-      (define-key py-mode-map [(meta tab)] 'ipython-complete)
-      
-      )
-    (add-hook 'py-shell-hook 'ipython-shell-hook)
-    ;; Regular expression that describes tracebacks for IPython in context and
-    ;; verbose mode. 
-  
-    ;;Adapt python-mode settings for ipython.
-    ;; (this works for %xmode 'verbose' or 'context')
-
-    ;; XXX putative regexps for syntax errors; unfortunately the 
-    ;;     current python-mode traceback-line-re scheme is too primitive,
-    ;;     so it's either matching syntax errors, *or* everything else
-    ;;     (XXX: should ask Fernando for a change)
-    ;;"^   File \"\\(.*?\\)\", line \\([0-9]+\\).*\n.*\n.*\nSyntaxError:"
-    ;;^   File \"\\(.*?\\)\", line \\([0-9]+\\)"
-
-    (setq py-traceback-line-re
-          "\\(^[^\t >].+?\\.py\\).*\n   +[0-9]+[^\00]*?\n-+> \\([0-9]+\\)+")
-
-    
-    ;; Recognize the ipython pdb, whose prompt is 'ipdb>' or  'ipydb>'
-    ;;instead of '(Pdb)'
-    (setq py-pdbtrack-input-prompt "\n[(<]*[Ii]?[Pp]y?db[>)]+ ")
-    (setq pydb-pydbtrack-input-prompt "\n[(]*ipydb[>)]+ ")
-    
-    (setq py-shell-input-prompt-1-regexp "^In \\[[0-9]+\\]: *"
-          py-shell-input-prompt-2-regexp "^   [.][.][.]+: *" )
-    ;; select a suitable color-scheme
-    (unless (member "-colors" py-python-command-args)
-      (setq py-python-command-args 
-            (nconc py-python-command-args 
-                   (list "-colors"
-                         (cond  
-                           ((eq frame-background-mode 'dark)
-                            "Linux")
-                           ((eq frame-background-mode 'light)
-                            "LightBG")
-                           (t ; default (backg-mode isn't always set by XEmacs)
-                            "LightBG"))))))
-    (unless (equal ipython-backup-of-py-python-command py-python-command)
-      (setq ipython-backup-of-py-python-command py-python-command))
-    (setq py-python-command ipython-command))
-
-
-;; MODIFY py-shell so that it loads the editing history
-(defadvice py-shell (around py-shell-with-history)
-  "Add persistent command-history support (in
-$PYTHONHISTORY (or \"~/.ipython/history\", if we use IPython)). Also, if
-`py-shell-initial-switch-buffers' is nil, it only switches to *Python* if that
-buffer already exists."
-  (if (comint-check-proc "*Python*")
-      ad-do-it
-    (setq comint-input-ring-file-name
-          (if (string-equal py-python-command ipython-command)
-              (concat (or (getenv "IPYTHONDIR") "~/.ipython") "/history")
-            (or (getenv "PYTHONHISTORY") "~/.python-history.py")))
-    (comint-read-input-ring t)
-    (let ((buf (current-buffer)))
-      ad-do-it
-      (unless py-shell-initial-switch-buffers
-        (switch-to-buffer-other-window buf)))))
-(ad-activate 'py-shell)
-;; (defadvice py-execute-region (before py-execute-buffer-ensure-process)
-;;   "HACK: test that ipython is already running before executing something.
-;;   Doing this properly seems not worth the bother (unless people actually
-;;   request it)."
-;; (unless (comint-check-proc "*Python*")
-;;     (error "Sorry you have to first do M-x py-shell to send something to ipython.")))
-;; (ad-activate 'py-execute-region)
-
-(defadvice py-execute-region (around py-execute-buffer-ensure-process)
-  "HACK: if `py-shell' is not active or ASYNC is explicitly desired, fall back
-  to python instead of ipython." 
-  (let ((py-which-shell (if (and (comint-check-proc "*Python*") (not async))
-			    py-python-command
-			  ipython-backup-of-py-python-command)))
-    ad-do-it))
-(ad-activate 'py-execute-region)
-
-(defun ipython-to-doctest (start end)
-  "Transform a cut-and-pasted bit from an IPython session into something that
-looks like it came from a normal interactive python session, so that it can
-be used in doctests. Example:
-
-
-    In [1]: import sys
-    
-    In [2]: sys.stdout.write 'Hi!\n'
-    ------> sys.stdout.write ('Hi!\n')
-    Hi!
-    
-    In [3]: 3 + 4
-    Out[3]: 7
-    
-gets converted to:
-
-    >>> import sys
-    >>> sys.stdout.write ('Hi!\n')
-    Hi!
-    >>> 3 + 4
-    7
-
-"
-  (interactive "*r\n")
-  ;(message (format "###DEBUG s:%de:%d" start end))
-  (save-excursion
-    (save-match-data
-      ;; replace ``In [3]: bla`` with ``>>> bla`` and 
-      ;;         ``... :   bla`` with ``...    bla``
-      (goto-char start)
-      (while (re-search-forward ipython-de-input-prompt-regexp end t)
-        ;(message "finding 1")
-        (cond ((match-string 3)         ;continued
-               (replace-match "... \\3" t nil))
-              (t
-               (replace-match ">>> \\1\\2" t nil))))
-      ;; replace ``
-      (goto-char start)
-      (while (re-search-forward ipython-de-output-prompt-regexp end t)
-        (replace-match "" t nil)))))
-
-(defvar ipython-completion-command-string 
-  "print ';'.join(__IP.Completer.all_completions('%s')) #PYTHON-MODE SILENT\n"
-  "The string send to ipython to query for all possible completions")
-
-
-;; xemacs doesn't have `comint-preoutput-filter-functions' so we'll try the
-;; following wonderful hack to work around this case
-(if (featurep 'xemacs)
-    ;;xemacs
-    (defun ipython-complete ()
-      "Try to complete the python symbol before point. Only knows about the stuff
-in the current *Python* session."
-      (interactive)
-      (let* ((ugly-return nil)
-             (sep ";")
-             (python-process (or (get-buffer-process (current-buffer))
-                                 ;XXX hack for .py buffers
-                                 (get-process py-which-bufname)))
-             ;; XXX currently we go backwards to find the beginning of an
-             ;; expression part; a more powerful approach in the future might be
-             ;; to let ipython have the complete line, so that context can be used
-             ;; to do things like filename completion etc.
-             (beg (save-excursion (skip-chars-backward "a-z0-9A-Z_." (point-at-bol))
-                                  (point)))
-             (end (point))
-             (pattern (buffer-substring-no-properties beg end))
-             (completions nil)
-             (completion-table nil)
-             completion
-             (comint-output-filter-functions
-              (append comint-output-filter-functions 
-                      '(ansi-color-filter-apply
-                        (lambda (string) 
-                                        ;(message (format "DEBUG filtering: %s" string))
-                          (setq ugly-return (concat ugly-return string))
-                          (delete-region comint-last-output-start 
-                                         (process-mark (get-buffer-process (current-buffer)))))))))
-                                        ;(message (format "#DEBUG pattern: '%s'" pattern))
-        (process-send-string python-process 
-                              (format ipython-completion-command-string pattern))
-        (accept-process-output python-process)
-                                        ;(message (format "DEBUG return: %s" ugly-return))
-        (setq completions 
-              (split-string (substring ugly-return 0 (position ?\n ugly-return)) sep))
-        (setq completion-table (loop for str in completions
-                                     collect (list str nil)))
-        (setq completion (try-completion pattern completion-table))
-        (cond ((eq completion t))
-              ((null completion)
-               (message "Can't find completion for \"%s\"" pattern)
-               (ding))
-              ((not (string= pattern completion))
-               (delete-region beg end)
-               (insert completion))
-              (t
-               (message "Making completion list...")
-               (with-output-to-temp-buffer "*Python Completions*"
-                 (display-completion-list (all-completions pattern completion-table)))
-               (message "Making completion list...%s" "done")))))
-  ;; emacs
-  (defun ipython-complete ()
-    "Try to complete the python symbol before point. Only knows about the stuff
-in the current *Python* session."
-    (interactive)
-    (let* ((ugly-return nil)
-           (sep ";")
-           (python-process (or (get-buffer-process (current-buffer))
-                                        ;XXX hack for .py buffers
-                               (get-process py-which-bufname)))
-           ;; XXX currently we go backwards to find the beginning of an
-           ;; expression part; a more powerful approach in the future might be
-           ;; to let ipython have the complete line, so that context can be used
-           ;; to do things like filename completion etc.
-           (beg (save-excursion (skip-chars-backward "a-z0-9A-Z_." (point-at-bol))
-                                (point))) 
-           (end (point))
-           (pattern (buffer-substring-no-properties beg end))
-           (completions nil)
-           (completion-table nil)
-           completion
-         (comint-preoutput-filter-functions
-          (append comint-preoutput-filter-functions 
-                  '(ansi-color-filter-apply
-                    (lambda (string) 
-                      (setq ugly-return (concat ugly-return string))
-                      "")))))
-      (process-send-string python-process 
-                            (format ipython-completion-command-string pattern))
-      (accept-process-output python-process)
-      (setq completions 
-            (split-string (substring ugly-return 0 (position ?\n ugly-return)) sep))
-                                        ;(message (format "DEBUG completions: %S" completions))
-      (setq completion-table (loop for str in completions
-                                   collect (list str nil)))
-      (setq completion (try-completion pattern completion-table))
-      (cond ((eq completion t))
-            ((null completion)
-             (message "Can't find completion for \"%s\"" pattern)
-             (ding))
-            ((not (string= pattern completion))
-             (delete-region beg end)
-             (insert completion))
-            (t
-             (message "Making completion list...")
-             (with-output-to-temp-buffer "*IPython Completions*"
-               (display-completion-list (all-completions pattern completion-table)))
-             (message "Making completion list...%s" "done")))))
-)
-
-;;; autoindent support: patch sent in by Jin Liu <m.liu.jin@gmail.com>,
-;;; originally written by doxgen@newsmth.net
-;;; Minor modifications by fperez for xemacs compatibility.
-
-(defvar ipython-autoindent t
- "If non-nil, enable autoindent for IPython shell through python-mode.")
-
-(defvar ipython-indenting-buffer-name "*IPython Indentation Calculation*"
- "Temporary buffer for indenting multiline statement.")
-
-(defun ipython-get-indenting-buffer ()
- "Return a temporary buffer set in python-mode. Create one if necessary."
- (let ((buf (get-buffer-create ipython-indenting-buffer-name)))
-   (set-buffer buf)
-   (unless (eq major-mode 'python-mode)
-     (python-mode))
-   buf))
-
-(defvar ipython-indentation-string nil
- "Indentation for the next line in a multiline statement.")
-
-(defun ipython-send-and-indent ()
- "Send the current line to IPython, and calculate the indentation for
-the next line."
- (interactive)
- (if ipython-autoindent
-     (let ((line (buffer-substring (point-at-bol) (point)))
-           (after-prompt1)
-           (after-prompt2))
-       (save-excursion
-           (comint-bol t)
-           (if (looking-at py-shell-input-prompt-1-regexp)
-               (setq after-prompt1 t)
-             (setq after-prompt2 (looking-at py-shell-input-prompt-2-regexp)))
-           (with-current-buffer (ipython-get-indenting-buffer)
-             (when after-prompt1
-               (erase-buffer))
-             (when (or after-prompt1 after-prompt2)
-               (delete-region (point-at-bol) (point))
-               (insert line)
-               (newline-and-indent))))))
- ;; send input line to ipython interpreter
- (comint-send-input))
-
-(defun ipython-indentation-hook (string)
- "Insert indentation string if py-shell-input-prompt-2-regexp
-matches last process output."
- (let* ((start-marker (or comint-last-output-start
-                          (point-min-marker)))
-        (end-marker (process-mark (get-buffer-process (current-buffer))))
-        (text (ansi-color-filter-apply (buffer-substring start-marker end-marker))))
-   ;; XXX if `text' matches both pattern, it MUST be the last prompt-2
-   (when (and (string-match py-shell-input-prompt-2-regexp text)
-	      (not (string-match "\n$" text)))
-     (with-current-buffer (ipython-get-indenting-buffer)
-       (setq ipython-indentation-string
-	     (buffer-substring (point-at-bol) (point))))
-     (goto-char end-marker)
-     (insert ipython-indentation-string)
-     (setq ipython-indentation-string nil))))
-
-(add-hook 'py-shell-hook
-         (lambda ()
-           (add-hook 'comint-output-filter-functions
-                     'ipython-indentation-hook)))
-
-(define-key py-shell-map (kbd "RET") 'ipython-send-and-indent)
-;;; / end autoindent support
-
-(provide 'ipython)
deleted file mode 100644
--- a/.elisp/js2.el
+++ /dev/null
@@ -1,11659 +0,0 @@
-;;; js2.el -- an improved JavaScript editing mode
-;;;
-;;; This file was auto-generated on Mon Jun 16 01:46:45 2008 from files:
-;;;  js2-vars.el
-;;;  js2-util.el
-;;;  js2-scan.el
-;;;  js2-messages.el
-;;;  js2-ast.el
-;;;  js2-highlight.el
-;;;  js2-browse.el
-;;;  js2-parse.el
-;;;  js2-indent.el
-;;;  js2-mode.el
-
-;;; js2-mode.el --- an improved JavaScript editing mode
-
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Version: 20080616
-;; Keywords:  javascript languages
-
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License as
-;; published by the Free Software Foundation; either version 2 of
-;; the License, or (at your option) any later version.
-
-;; This program is distributed in the hope that it will be
-;; useful, but WITHOUT ANY WARRANTY; without even the implied
-;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-;; PURPOSE.  See the GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public
-;; License along with this program; if not, write to the Free
-;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-;; MA 02111-1307 USA
-
-;;; Commentary:
-
-;; This JavaScript editing mode supports:
-;;
-;;  - the full JavaScript language through version 1.7
-;;  - support for most Rhino and SpiderMonkey extensions from 1.5 to 1.7
-;;  - accurate syntax highlighting using a recursive-descent parser
-;;  - syntax-error and strict-mode warning reporting
-;;  - "bouncing" line indentation to choose among alternate indentation points
-;;  - smart line-wrapping within comments (Emacs 22+) and strings
-;;  - code folding:
-;;    - show some or all function bodies as {...}
-;;    - show some or all block comments as /*...*/
-;;  - context-sensitive menu bar and popup menus
-;;  - code browsing using the `imenu' package
-;;  - typing helpers (e.g. inserting matching braces/parens)
-;;  - many customization options
-;;
-;; It is only compatible with GNU Emacs versions 21 and higher (not XEmacs).
-;;
-;; Installation:
-;;
-;;  - put `js2.el' somewhere in your emacs load path
-;;  - M-x byte-compile-file RET <path-to-js2.el> RET
-;;    Note:  it will refuse to run unless byte-compiled
-;;  - add these lines to your .emacs file:
-;;    (autoload 'js2-mode "js2" nil t)
-;;    (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
-;;
-;; To customize how it works:
-;;   M-x customize-group RET js2-mode RET
-;;
-;; The variable `js2-mode-version' is a date stamp.  When you upgrade
-;; to a newer version, you must byte-compile the file again.
-;;
-;; Notes:
-;;
-;; This mode is different in many ways from standard Emacs language editing
-;; modes, inasmuch as it attempts to be more like an IDE.  If this drives
-;; you crazy, it IS possible to customize it to be more like other Emacs
-;; editing modes.  Please customize the group `js2-mode' to see all of the
-;; configuration options.
-;;
-;; Some of the functionality does not work in Emacs 21 -- upgrading to
-;; Emacs 22 or higher will get you better results.  If you byte-compiled
-;; js2.el with Emacs 21, you should re-compile it for Emacs 22.
-;;
-;; Unlike cc-engine based language modes, js2-mode's line-indentation is not
-;; customizable.  It is a surprising amount of work to support customizable
-;; indentation.  The current compromise is that the tab key lets you cycle among
-;; various likely indentation points, similar to the behavior of python-mode.
-;;
-;; This mode does not yet work with "multi-mode" modes such as mmm-mode
-;; and mumamo, although it could possibly be made to do so with some effort.
-;; This means that js2-mode is currently only useful for editing JavaScript
-;; files, and not for editing JavaScript within <script> tags or templates.
-;;
-;; This code is part of a larger project, in progress, to enable writing
-;; Emacs customizations in JavaScript.
-;;
-;; Please email bug reports and suggestions to the author, or submit them
-;; at http://code.google.com/p/js2-mode/issues
-
-;; TODO:
-;;  - add unreachable-code warning (error?) using the inconsistent-return analysis
-;;  - labeled stmt length is now 1
-;;  - "anonymous function does not always return a value" - use getter/setter name
-;;  - extend js2-missing-semi-one-line-override to handle catch (e) {return x}
-;;  - set a text prop on autoinserted delimiters and don't biff user-entered ones
-;;  - when inserting magic curlies, look for matching close-curly before inserting
-;;  - get more use out of the symbol table:
-;;    - jump to declaration (put hyperlinks on all non-decl var usages?)
-;;    - rename variable/function
-;;    - warn on unused var
-;;  - add some dabbrev-expansions for built-in keywords like finally, function
-;;  - add at least some completion support, e.g. for built-ins
-;;  - code formatting
-
-;;; Code:
-;;; js2-vars.el -- byte-compiler support for js2-mode
-
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Keywords:  javascript languages
-
-;;; Code:
-
-(eval-when-compile
-  (require 'cl))
-
-(eval-and-compile
-  (require 'cc-mode)     ; (only) for `c-populate-syntax-table'
-  (require 'cc-langs)    ; it's here in Emacs 21...
-  (require 'cc-engine))  ; for `c-paragraph-start' et. al.
-
-(defvar js2-emacs22 (>= emacs-major-version 22))
-
-(defcustom js2-highlight-level 2
-  "Amount of syntax highlighting to perform.
-nil, zero or negative means none.
-1 adds basic syntax highlighting.
-2 adds highlighting of some Ecma built-in properties.
-3 adds highlighting of many Ecma built-in functions."
-  :type 'integer
-  :group 'js2-mode)
-
-(defvar js2-mode-dev-mode-p nil
-  "Non-nil if running in development mode.  Normally nil.")
-
-(defgroup js2-mode nil
-  "An improved JavaScript mode."
-  :group 'languages)
-
-(defcustom js2-basic-offset (if (and (boundp 'c-basic-offset)
-                                     (numberp c-basic-offset))
-                                c-basic-offset
-                              2)
-  "Number of spaces to indent nested statements.
-Similar to `c-basic-offset'."
-  :group 'js2-mode
-  :type 'integer)
-(make-variable-buffer-local 'js2-basic-offset)
-
-(defcustom js2-cleanup-whitespace t
-  "Non-nil to invoke `delete-trailing-whitespace' before saves."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-move-point-on-right-click t
-  "Non-nil to move insertion point when you right-click.
-This makes right-click context menu behavior a bit more intuitive,
-since menu operations generally apply to the point.  The exception
-is if there is a region selection, in which case the point does -not-
-move, so cut/copy/paste etc. can work properly.
-
-Note that IntelliJ moves the point, and Eclipse leaves it alone,
-so this behavior is customizable."
-  :group 'js2-mode
-  :type 'boolean)
-
-(defcustom js2-mirror-mode t
-  "Non-nil to insert closing brackets, parens, etc. automatically."
-  :group 'js2-mode
-  :type 'boolean)
-
-(defcustom js2-auto-indent-flag t
-  "Automatic indentation with punctuation characters. If non-nil, the
-current line is indented when certain punctuations are inserted."
-  :group 'js2-mode
-  :type 'boolean)
-
-(defcustom js2-bounce-indent-flag t
-  "Non-nil to have indent-line function choose among alternatives.
-If nil, the indent-line function will indent to a predetermined column
-based on heuristic guessing.  If non-nil, then if the current line is
-already indented to that predetermined column, indenting will choose
-another likely column and indent to that spot.  Repeated invocation of
-the indent-line function will cycle among the computed alternatives.
-See the function `js2-bounce-indent' for details."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-indent-on-enter-key nil
-  "Non-nil to have Enter/Return key indent the line.
-This is unusual for Emacs modes but common in IDEs like Eclipse."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-enter-indents-newline t
-  "Non-nil to have Enter/Return key indent the newly-inserted line.
-This is unusual for Emacs modes but common in IDEs like Eclipse."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-rebind-eol-bol-keys t
-  "Non-nil to rebind beginning-of-line and end-of-line keys.
-If non-nil, bounce between bol/eol and first/last non-whitespace char."
-  :group 'js2-mode
-  :type 'boolean)
-
-(defcustom js2-electric-keys '("{" "}" "(" ")" "[" "]" ":" ";" "," "*")
-  "Keys that auto-indent when `js2-auto-indent-flag' is non-nil.
-Each value in the list is passed to `define-key'."
-  :type 'list
-  :group 'js2-mode)
-
-(defcustom js2-idle-timer-delay 0.2
-  "Delay in secs before re-parsing after user makes changes.
-Multiplied by `js2-dynamic-idle-timer-adjust', which see."
-  :type 'number
-  :group 'js2-mode)
-(make-variable-buffer-local 'js2-idle-timer-delay)
-
-(defcustom js2-dynamic-idle-timer-adjust 0
-  "Positive to adjust `js2-idle-timer-delay' based on file size.
-The idea is that for short files, parsing is faster so we can be
-more responsive to user edits without interfering with editing.
-The buffer length in characters (typically bytes) is divided by
-this value and used to multiply `js2-idle-timer-delay' for the
-buffer.  For example, a 21k file and 10k adjust yields 21k/10k
-== 2, so js2-idle-timer-delay is multiplied by 2.
-If `js2-dynamic-idle-timer-adjust' is 0 or negative,
-`js2-idle-timer-delay' is not dependent on the file size."
-  :type 'number
-  :group 'js2-mode)
-
-(defcustom js2-mode-escape-quotes t
-  "Non-nil to disable automatic quote-escaping inside strings."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-mode-squeeze-spaces t
-  "Non-nil to normalize whitespace when filling in comments.
-Multiple runs of spaces are converted to a single space."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-mode-show-parse-errors t
-  "True to highlight parse errors."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-mode-show-strict-warnings t
-  "Non-nil to emit Ecma strict-mode warnings.
-Some of the warnings can be individually disabled by other flags,
-even if this flag is non-nil."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-strict-trailing-comma-warning t
-  "Non-nil to warn about trailing commas in array literals.
-Ecma-262 forbids them, but many browsers permit them.  IE is the
-big exception, and can produce bugs if you have trailing commas."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-strict-missing-semi-warning t
-  "Non-nil to warn about semicolon auto-insertion after statement.
-Technically this is legal per Ecma-262, but some style guides disallow
-depending on it."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-missing-semi-one-line-override nil
-  "Non-nil to permit missing semicolons in one-line functions.
-In one-liner functions such as `function identity(x) {return x}'
-people often omit the semicolon for a cleaner look.  If you are
-such a person, you can suppress the missing-semicolon warning
-by setting this variable to t."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-strict-inconsistent-return-warning t
-  "Non-nil to warn about mixing returns with value-returns.
-It's perfectly legal to have a `return' and a `return foo' in the
-same function, but it's often an indicator of a bug, and it also
-interferes with type inference (in systems that support it.)"
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-strict-cond-assign-warning t
-  "Non-nil to warn about expressions like if (a = b).
-This often should have been '==' instead of '='.  If the warning
-is enabled, you can suppress it on a per-expression basis by
-parenthesizing the expression, e.g. if ((a = b)) ..."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-strict-cond-assign-warning t
-  "Non-nil to warn about expressions like if (a = b).
-This often should have been '==' instead of '='.  If the warning
-is enabled, you can suppress it on a per-expression basis by
-parenthesizing the expression, e.g. if ((a = b)) ..."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-strict-var-redeclaration-warning t
-  "Non-nil to warn about redeclaring variables in a script or function."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-strict-var-hides-function-arg-warning t
-  "Non-nil to warn about a var decl hiding a function argument."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-skip-preprocessor-directives nil
-  "Non-nil to treat lines beginning with # as comments.
-Useful for viewing Mozilla JavaScript source code."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-basic-offset c-basic-offset
-  "Functions like `c-basic-offset' in js2-mode buffers."
-  :type 'integer
-  :group 'js2-mode)
-(make-variable-buffer-local 'js2-basic-offset)
-
-(defcustom js2-language-version 170
-  "Configures what JavaScript language version to recognize.
-Currently only 150, 160 and 170 are supported, corresponding
-to JavaScript 1.5, 1.6 and 1.7, respectively.  In a nutshell,
-1.6 adds E4X support, and 1.7 adds let, yield, and Array
-comprehensions."
-  :type 'integer
-  :group 'js2-mode)
-
-(defcustom js2-allow-keywords-as-property-names t
-  "If non-nil, you can use JavaScript keywords as object property names.
-Examples:
-
-  var foo = {int: 5, while: 6, continue: 7};
-  foo.return = 8;
-
-Ecma-262 forbids this syntax, but many browsers support it."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-instanceof-has-side-effects nil
-  "If non-nil, treats the instanceof operator as having side effects.
-This is useful for xulrunner apps."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-allow-rhino-new-expr-initializer nil
-  "Non-nil to support a Rhino's experimental syntactic construct.
-
-Rhino supports the ability to follow a `new' expression with an object
-literal, which is used to set additional properties on the new object
-after calling its constructor.  Syntax:
-
-  new <expr> [ ( arglist ) ] [initializer]
-
-Hence, this expression:
-
-  new Object {a: 1, b: 2}
-
-results in an Object with properties a=1 and b=2.  This syntax is
-apparently not configurable in Rhino - it's currently always enabled,
-as of Rhino version 1.7R2."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-allow-member-expr-as-function-name nil
-  "Non-nil to support experimental Rhino syntax for function names.
-
-Rhino supports an experimental syntax configured via the Rhino Context
-setting `allowMemberExprAsFunctionName'.  The experimental syntax is:
-
-  function <member-expr> ( [ arg-list ] ) { <body> }
-
-Where member-expr is a non-parenthesized 'member expression', which
-is anything at the grammar level of a new-expression or lower, meaning
-any expression that does not involve infix or unary operators.
-
-When <member-expr> is not a simple identifier, then it is syntactic
-sugar for assigning the anonymous function to the <member-expr>.  Hence,
-this code:
-
-  function a.b().c[2] (x, y) { ... }
-
-is rewritten as:
-
-  a.b().c[2] = function(x, y) {...}
-
-which doesn't seem particularly useful, but Rhino permits it."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defvar js2-mode-version 20080616
-  "Release number for `js2-mode'.")
-
-;; scanner variables
-
-;; We record the start and end position of each token.
-(defvar js2-token-beg 1)
-(make-variable-buffer-local 'js2-token-beg)
-(defvar js2-token-end -1)
-(make-variable-buffer-local 'js2-token-end)
-
-(defvar js2-EOF_CHAR -1
-  "Represents end of stream.  Distinct from js2-EOF token type.")
-
-;; I originally used symbols to represent tokens, but Rhino uses
-;; ints and then sets various flag bits in them, so ints it is.
-;; The upshot is that we need a `js2-' prefix in front of each name.
-(defvar js2-ERROR -1)
-(defvar js2-EOF 0)
-(defvar js2-EOL 1)
-(defvar js2-ENTERWITH 2)       ; begin interpreter bytecodes
-(defvar js2-LEAVEWITH 3)
-(defvar js2-RETURN 4)
-(defvar js2-GOTO 5)
-(defvar js2-IFEQ 6)
-(defvar js2-IFNE 7)
-(defvar js2-SETNAME 8)
-(defvar js2-BITOR 9)
-(defvar js2-BITXOR 10)
-(defvar js2-BITAND 11)
-(defvar js2-EQ 12)
-(defvar js2-NE 13)
-(defvar js2-LT 14)
-(defvar js2-LE 15)
-(defvar js2-GT 16)
-(defvar js2-GE 17)
-(defvar js2-LSH 18)
-(defvar js2-RSH 19)
-(defvar js2-URSH 20)
-(defvar js2-ADD 21)            ; infix plus
-(defvar js2-SUB 22)            ; infix minus
-(defvar js2-MUL 23)
-(defvar js2-DIV 24)
-(defvar js2-MOD 25)
-(defvar js2-NOT 26)
-(defvar js2-BITNOT 27)
-(defvar js2-POS 28)            ; unary plus
-(defvar js2-NEG 29)            ; unary minus
-(defvar js2-NEW 30)
-(defvar js2-DELPROP 31)
-(defvar js2-TYPEOF 32)
-(defvar js2-GETPROP 33)
-(defvar js2-GETPROPNOWARN 34)
-(defvar js2-SETPROP 35)
-(defvar js2-GETELEM 36)
-(defvar js2-SETELEM 37)
-(defvar js2-CALL 38)
-(defvar js2-NAME 39)           ; an identifier
-(defvar js2-NUMBER 40)
-(defvar js2-STRING 41)
-(defvar js2-NULL 42)
-(defvar js2-THIS 43)
-(defvar js2-FALSE 44)
-(defvar js2-TRUE 45)
-(defvar js2-SHEQ 46)           ; shallow equality (===)
-(defvar js2-SHNE 47)           ; shallow inequality (!==)
-(defvar js2-REGEXP 48)
-(defvar js2-BINDNAME 49)
-(defvar js2-THROW 50)
-(defvar js2-RETHROW 51)        ; rethrow caught exception: catch (e if ) uses it
-(defvar js2-IN 52)
-(defvar js2-INSTANCEOF 53)
-(defvar js2-LOCAL_LOAD 54)
-(defvar js2-GETVAR 55)
-(defvar js2-SETVAR 56)
-(defvar js2-CATCH_SCOPE 57)
-(defvar js2-ENUM_INIT_KEYS 58)
-(defvar js2-ENUM_INIT_VALUES 59)
-(defvar js2-ENUM_INIT_ARRAY 60)
-(defvar js2-ENUM_NEXT 61)
-(defvar js2-ENUM_ID 62)
-(defvar js2-THISFN 63)
-(defvar js2-RETURN_RESULT 64)  ; to return previously stored return result
-(defvar js2-ARRAYLIT 65)       ; array literal
-(defvar js2-OBJECTLIT 66)      ; object literal
-(defvar js2-GET_REF 67)        ; *reference
-(defvar js2-SET_REF 68)        ; *reference = something
-(defvar js2-DEL_REF 69)        ; delete reference
-(defvar js2-REF_CALL 70)       ; f(args) = something or f(args)++
-(defvar js2-REF_SPECIAL 71)    ; reference for special properties like __proto
-(defvar js2-YIELD 72)          ; JS 1.7 yield pseudo keyword
-
-;; XML support
-(defvar js2-DEFAULTNAMESPACE 73)
-(defvar js2-ESCXMLATTR 74)
-(defvar js2-ESCXMLTEXT 75)
-(defvar js2-REF_MEMBER 76)     ; Reference for x.@y, x..y etc.
-(defvar js2-REF_NS_MEMBER 77)  ; Reference for x.ns::y, x..ns::y etc.
-(defvar js2-REF_NAME 78)       ; Reference for @y, @[y] etc.
-(defvar js2-REF_NS_NAME 79)    ; Reference for ns::y, @ns::y@[y] etc.
-
-(defvar js2-first-bytecode js2-ENTERWITH)
-(defvar js2-last-bytecode js2-REF_NS_NAME)
-
-(defvar js2-TRY 80)
-(defvar js2-SEMI 81)           ; semicolon
-(defvar js2-LB 82)             ; left and right brackets
-(defvar js2-RB 83)
-(defvar js2-LC 84)             ; left and right curly-braces
-(defvar js2-RC 85)
-(defvar js2-LP 86)             ; left and right parens
-(defvar js2-RP 87)
-(defvar js2-COMMA 88)          ; comma operator
-
-(defvar js2-ASSIGN 89)         ; simple assignment (=)
-(defvar js2-ASSIGN_BITOR 90)   ; |=
-(defvar js2-ASSIGN_BITXOR 91)  ; ^=
-(defvar js2-ASSIGN_BITAND 92)  ; &=
-(defvar js2-ASSIGN_LSH 93)     ; <<=
-(defvar js2-ASSIGN_RSH 94)     ; >>=
-(defvar js2-ASSIGN_URSH 95)    ; >>>=
-(defvar js2-ASSIGN_ADD 96)     ; +=
-(defvar js2-ASSIGN_SUB 97)     ; -=
-(defvar js2-ASSIGN_MUL 98)     ; *=
-(defvar js2-ASSIGN_DIV 99)     ; /=
-(defvar js2-ASSIGN_MOD 100)    ; %=
-
-(defvar js2-first-assign js2-ASSIGN)
-(defvar js2-last-assign js2-ASSIGN_MOD)
-
-(defvar js2-HOOK 101)          ; conditional (?:)
-(defvar js2-COLON 102)
-(defvar js2-OR 103)            ; logical or (||)
-(defvar js2-AND 104)           ; logical and (&&)
-(defvar js2-INC 105)           ; increment/decrement (++ --)
-(defvar js2-DEC 106)
-(defvar js2-DOT 107)           ; member operator (.)
-(defvar js2-FUNCTION 108)      ; function keyword
-(defvar js2-EXPORT 109)        ; export keyword
-(defvar js2-IMPORT 110)        ; import keyword
-(defvar js2-IF 111)            ; if keyword
-(defvar js2-ELSE 112)          ; else keyword
-(defvar js2-SWITCH 113)        ; switch keyword
-(defvar js2-CASE 114)          ; case keyword
-(defvar js2-DEFAULT 115)       ; default keyword
-(defvar js2-WHILE 116)         ; while keyword
-(defvar js2-DO 117)            ; do keyword
-(defvar js2-FOR 118)           ; for keyword
-(defvar js2-BREAK 119)         ; break keyword
-(defvar js2-CONTINUE 120)      ; continue keyword
-(defvar js2-VAR 121)           ; var keyword
-(defvar js2-WITH 122)          ; with keyword
-(defvar js2-CATCH 123)         ; catch keyword
-(defvar js2-FINALLY 124)       ; finally keyword
-(defvar js2-VOID 125)          ; void keyword
-(defvar js2-RESERVED 126)      ; reserved keywords
-
-(defvar js2-EMPTY 127)
-
-;; Types used for the parse tree - never returned by scanner.
-
-(defvar js2-BLOCK 128)         ; statement block
-(defvar js2-LABEL 129)         ; label
-(defvar js2-TARGET 130)
-(defvar js2-LOOP 131)
-(defvar js2-EXPR_VOID 132)     ; expression statement in functions
-(defvar js2-EXPR_RESULT 133)   ; expression statement in scripts
-(defvar js2-JSR 134)
-(defvar js2-SCRIPT 135)        ; top-level node for entire script
-(defvar js2-TYPEOFNAME 136)    ; for typeof(simple-name)
-(defvar js2-USE_STACK 137)
-(defvar js2-SETPROP_OP 138)    ; x.y op= something
-(defvar js2-SETELEM_OP 139)    ; x[y] op= something
-(defvar js2-LOCAL_BLOCK 140)
-(defvar js2-SET_REF_OP 141)    ; *reference op= something
-
-;; For XML support:
-(defvar js2-DOTDOT 142)        ; member operator (..)
-(defvar js2-COLONCOLON 143)    ; namespace::name
-(defvar js2-XML 144)           ; XML type
-(defvar js2-DOTQUERY 145)      ; .() -- e.g., x.emps.emp.(name == "terry")
-(defvar js2-XMLATTR 146)       ; @
-(defvar js2-XMLEND 147)
-
-;; Optimizer-only tokens
-(defvar js2-TO_OBJECT 148)
-(defvar js2-TO_DOUBLE 149)
-
-(defvar js2-GET 150)           ; JS 1.5 get pseudo keyword
-(defvar js2-SET 151)           ; JS 1.5 set pseudo keyword
-(defvar js2-LET 152)           ; JS 1.7 let pseudo keyword
-(defvar js2-CONST 153)
-(defvar js2-SETCONST 154)
-(defvar js2-SETCONSTVAR 155)
-(defvar js2-ARRAYCOMP 156)
-(defvar js2-LETEXPR 157)
-(defvar js2-WITHEXPR 158)
-(defvar js2-DEBUGGER 159)
-
-(defvar js2-COMMENT 160)  ; not yet in Rhino
-
-(defvar js2-num-tokens (1+ js2-COMMENT))
-
-(defconst js2-debug-print-trees nil)
-
-;; Rhino accepts any string or stream as input.
-;; Emacs character processing works best in buffers, so we'll
-;; assume the input is a buffer.  JavaScript strings can be
-;; copied into temp buffers before scanning them.
-
-(defmacro deflocal (name value comment)
-  `(progn
-     (defvar ,name ,value ,comment)
-     (make-variable-buffer-local ',name)))
-
-;; Buffer-local variables yield much cleaner code than using `defstruct'.
-;; They're the Emacs equivalent of instance variables, more or less.
-
-(deflocal js2-ts-dirty-line nil
-  "Token stream buffer-local variable.
-Indicates stuff other than whitespace since start of line.")
-
-(deflocal js2-ts-regexp-flags nil
-  "Token stream buffer-local variable.")
-
-(deflocal js2-ts-string ""
-  "Token stream buffer-local variable.
-Last string scanned.")
-
-(deflocal js2-ts-number nil
-  "Token stream buffer-local variable.
-Last literal number scanned.")
-
-(deflocal js2-ts-hit-eof nil
-  "Token stream buffer-local variable.")
-
-(deflocal js2-ts-line-start 0
-  "Token stream buffer-local variable.")
-
-(deflocal js2-ts-lineno 1
-  "Token stream buffer-local variable.")
-
-(deflocal js2-ts-line-end-char -1
-  "Token stream buffer-local variable.")
-
-(deflocal js2-ts-cursor 1  ; emacs buffers are 1-indexed
-  "Token stream buffer-local variable.
-Current scan position.")
-
-(deflocal js2-ts-is-xml-attribute nil
-  "Token stream buffer-local variable.")
-
-(deflocal js2-ts-xml-is-tag-content nil
-  "Token stream buffer-local variable.")
-
-(deflocal js2-ts-xml-open-tags-count 0
-  "Token stream buffer-local variable.")
-
-(deflocal js2-ts-string-buffer nil
-  "Token stream buffer-local variable.
-List of chars built up while scanning various tokens.")
-
-(deflocal js2-ts-comment-type nil
-  "Token stream buffer-local variable.")
-
-;;; Parser variables
-
-(defvar js2-parsed-errors nil
-  "List of errors produced during scanning/parsing.")
-(make-variable-buffer-local 'js2-parsed-errors)
-
-(defvar js2-parsed-warnings nil
-  "List of warnings produced during scanning/parsing.")
-(make-variable-buffer-local 'js2-parsed-warnings)
-
-(defvar js2-recover-from-parse-errors t
-  "Non-nil to continue parsing after a syntax error.
-
-In recovery mode, the AST will be built in full, and any error
-nodes will be flagged with appropriate error information.  If
-this flag is nil, a syntax error will result in an error being
-signaled.
-
-The variable is automatically buffer-local, because different
-modes that use the parser will need different settings.")
-(make-variable-buffer-local 'js2-recover-from-parse-errors)
-
-(defvar js2-parse-hook nil
-  "List of callbacks for receiving parsing progress.")
-(make-variable-buffer-local 'js2-parse-hook)
-
-(defvar js2-parse-finished-hook nil
-  "List of callbacks to notify when parsing finishes.
-Not called if parsing was interrupted.")
-
-(defvar js2-is-eval-code nil
-  "True if we're evaluating code in a string.
-If non-nil, the tokenizer will record the token text, and the AST nodes
-will record their source text.  Off by default for IDE modes, since the
-text is available in the buffer.")
-(make-variable-buffer-local 'js2-is-eval-code)
-
-(defvar js2-parse-ide-mode t
-  "Non-nil if the parser is being used for `js2-mode'.
-If non-nil, the parser will set text properties for fontification
-and the syntax-table.  The value should be nil when using the
-parser as a frontend to an interpreter or byte compiler.")
-
-;;; Parser instance variables (buffer-local vars for js2-parse)
-
-(defconst js2-clear-ti-mask #xFFFF
-  "Mask to clear token information bits.")
-
-(defconst js2-ti-after-eol (lsh 1 16)
-  "Flag:  first token of the source line.")
-
-(defconst js2-ti-check-label (lsh 1 17)
-  "Flag:  indicates to check for label.")
-
-;; Inline Rhino's CompilerEnvirons vars as buffer-locals.
-
-(defvar js2-compiler-generate-debug-info t)
-(make-variable-buffer-local 'js2-compiler-generate-debug-info)
-
-(defvar js2-compiler-use-dynamic-scope nil)
-(make-variable-buffer-local 'js2-compiler-use-dynamic-scope)
-
-(defvar js2-compiler-reserved-keywords-as-identifier nil)
-(make-variable-buffer-local 'js2-compiler-reserved-keywords-as-identifier)
-
-(defvar js2-compiler-xml-available t)
-(make-variable-buffer-local 'js2-compiler-xml-available)
-
-(defvar js2-compiler-optimization-level 0)
-(make-variable-buffer-local 'js2-compiler-optimization-level)
-
-(defvar js2-compiler-generating-source t)
-(make-variable-buffer-local 'js2-compiler-generating-source)
-
-(defvar js2-compiler-strict-mode nil)
-(make-variable-buffer-local 'js2-compiler-strict-mode)
-
-(defvar js2-compiler-report-warning-as-error nil)
-(make-variable-buffer-local 'js2-compiler-report-warning-as-error)
-
-(defvar js2-compiler-generate-observer-count nil)
-(make-variable-buffer-local 'js2-compiler-generate-observer-count)
-
-(defvar js2-compiler-activation-names nil)
-(make-variable-buffer-local 'js2-compiler-activation-names)
-
-;; SKIP:  sourceURI
-
-;; There's a compileFunction method in Context.java - may need it.
-(defvar js2-called-by-compile-function nil
-  "True if `js2-parse' was called by `js2-compile-function'.
-Will only be used when we finish implementing the interpreter.")
-(make-variable-buffer-local 'js2-called-by-compile-function)
-
-;; SKIP:  ts  (we just call `js2-init-scanner' and use its vars)
-
-(defvar js2-current-flagged-token js2-EOF)
-(make-variable-buffer-local 'js2-current-flagged-token)
-
-(defvar js2-current-token js2-EOF)
-(make-variable-buffer-local 'js2-current-token)
-
-;; SKIP:  node factory - we're going to just call functions directly,
-;; and eventually go to a unified AST format.
-
-(defvar js2-nesting-of-function 0)
-(make-variable-buffer-local 'js2-nesting-of-function)
-
-(defvar js2-recorded-assignments nil)
-(make-variable-buffer-local 'js2-assignments-from-parse)
-
-;; SKIP:  decompiler
-;; SKIP:  encoded-source
-
-;;; These variables are per-function and should be saved/restored
-;;; during function parsing.
-
-(defvar js2-current-script-or-fn nil)
-(make-variable-buffer-local 'js2-current-script-or-fn)
-
-(defvar js2-current-scope nil)
-(make-variable-buffer-local 'js2-current-scope)
-
-(defvar js2-nesting-of-with 0)
-(make-variable-buffer-local 'js2-nesting-of-with)
-
-(defvar js2-label-set nil
-  "An alist mapping label names to nodes.")
-(make-variable-buffer-local 'js2-label-set)
-
-(defvar js2-loop-set nil)
-(make-variable-buffer-local 'js2-loop-set)
-
-(defvar js2-loop-and-switch-set nil)
-(make-variable-buffer-local 'js2-loop-and-switch-set)
-
-(defvar js2-has-return-value nil)
-(make-variable-buffer-local 'js2-has-return-value)
-
-(defvar js2-end-flags 0)
-(make-variable-buffer-local 'js2-end-flags)
-
-;;; end of per function variables
-
-;; Without 2-token lookahead, labels are a problem.
-;; These vars store the token info of the last matched name,
-;; iff it wasn't the last matched token.  Only valid in some contexts.
-(defvar js2-prev-name-token-start nil)
-(defvar js2-prev-name-token-string nil)
-
-(defsubst js2-save-name-token-data (pos name)
-  (setq js2-prev-name-token-start pos
-        js2-prev-name-token-string name))
-
-;; These flags enumerate the possible ways a statement/function can
-;; terminate. These flags are used by endCheck() and by the Parser to
-;; detect inconsistent return usage.
-;;
-;; END_UNREACHED is reserved for code paths that are assumed to always be
-;; able to execute (example: throw, continue)
-;;
-;; END_DROPS_OFF indicates if the statement can transfer control to the
-;; next one. Statement such as return dont. A compound statement may have
-;; some branch that drops off control to the next statement.
-;;
-;; END_RETURNS indicates that the statement can return (without arguments)
-;; END_RETURNS_VALUE indicates that the statement can return a value.
-;;
-;; A compound statement such as
-;; if (condition) {
-;;   return value;
-;; }
-;; Will be detected as (END_DROPS_OFF | END_RETURN_VALUE) by endCheck()
-
-(defconst js2-end-unreached     #x0)
-(defconst js2-end-drops-off     #x1)
-(defconst js2-end-returns       #x2)
-(defconst js2-end-returns-value #x4)
-(defconst js2-end-yields        #x8)
-
-;; Rhino awkwardly passes a statementLabel parameter to the
-;; statementHelper() function, the main statement parser, which
-;; is then used by quite a few of the sub-parsers.  We just make
-;; it a buffer-local variable and make sure it's cleaned up properly.
-(defvar js2-labeled-stmt nil)  ; type `js2-labeled-stmt-node'
-(make-variable-buffer-local 'js2-labeled-stmt)
-
-;; Similarly, Rhino passes an inForInit boolean through about half
-;; the expression parsers.  We use a dynamically-scoped variable,
-;; which makes it easier to funcall the parsers individually without
-;; worrying about whether they take the parameter or not.
-(defvar js2-in-for-init nil)
-(make-variable-buffer-local 'js2-in-for-init)
-
-(defvar js2-temp-name-counter 0)
-(make-variable-buffer-local 'js2-temp-name-counter)
-
-(defvar js2-parse-stmt-count 0)
-(make-variable-buffer-local 'js2-parse-stmt-count)
-
-(defsubst js2-get-next-temp-name ()
-  (format "$%d" (incf js2-temp-name-counter)))
-
-(defvar js2-parse-interruptable-p t
-  "Set this to nil to force parse to continue until finished.
-This will mostly be useful for interpreters.")
-
-(defvar js2-statements-per-pause 50
-  "Pause after this many statements to check for user input.
-If user input is pending, stop the parse and discard the tree.
-This makes for a smoother user experience for large files.
-You may have to wait a second or two before the highlighting
-and error-reporting appear, but you can always type ahead if
-you wish.  This appears to be more or less how Eclipse, IntelliJ
-and other editors work.")
-
-(defvar js2-record-comments t
-  "Instructs the scanner to record comments in `js2-scanned-comments'.")
-(make-variable-buffer-local 'js2-record-comments)
-
-(defvar js2-scanned-comments nil
-  "List of all comments from the current parse.")
-(make-variable-buffer-local 'js2-scanned-comments)
-
-(defun js2-underline-color (color)
-  "Return a legal value for the :underline face attribute based on COLOR."
-  ;; In XEmacs the :underline attribute can only be a boolean.
-  ;; In GNU it can be the name of a colour.
-  (if (featurep 'xemacs)
-      (if color t nil)
-    color))
-
-(defcustom js2-mode-indent-inhibit-undo nil
-  "Non-nil to disable collection of Undo information when indenting lines.
-Some users have requested this behavior.  It's nil by default because
-other Emacs modes don't work this way."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defcustom js2-mode-indent-ignore-first-tab nil
-  "If non-nil, ignore first TAB keypress if we look indented properly.
-It's fairly common for users to navigate to an already-indented line
-and press TAB for reassurance that it's been indented.  For this class
-of users, we want the first TAB press on a line to be ignored if the
-line is already indented to one of the precomputed alternatives.
-
-This behavior is only partly implemented.  If you TAB-indent a line,
-navigate to another line, and then navigate back, it fails to clear
-the last-indented variable, so it thinks you've already hit TAB once,
-and performs the indent.  A full solution would involve getting on the
-point-motion hooks for the entire buffer.  If we come across another
-use cases that requires watching point motion, I'll consider doing it.
-
-If you set this variable to nil, then the TAB key will always change
-the indentation of the current line, if more than one alternative
-indentation spot exists."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defvar js2-indent-hook nil
-  "A hook for user-defined indentation rules.
-
-Functions on this hook should expect two arguments:    (LIST INDEX)
-The LIST argument is the list of computed indentation points for
-the current line.  INDEX is the list index of the indentation point
-that `js2-bounce-indent' plans to use.  If INDEX is nil, then the
-indent function is not going to change the current line indentation.
-
-If a hook function on this list returns a non-nil value, then
-`js2-bounce-indent' assumes the hook function has performed its own
-indentation, and will do nothing.  If all hook functions on the list
-return nil, then `js2-bounce-indent' will use its computed indentation
-and reindent the line.
-
-When hook functions on this hook list are called, the variable
-`js2-mode-ast' may or may not be set, depending on whether the
-parse tree is available.  If the variable is nil, you can pass a
-callback to `js2-mode-wait-for-parse', and your callback will be
-called after the new parse tree is built.  This can take some time
-in large files.")
-
-(defface js2-warning-face
-  `((((class color) (background light))
-     (:underline ,(js2-underline-color "orange")))
-    (((class color) (background dark))
-     (:underline ,(js2-underline-color "orange")))
-    (t (:underline t)))
-  "Face for JavaScript warnings."
-  :group 'js2-mode)
-
-(defface js2-error-face
-  `((((class color) (background light))
-     (:foreground "red"))
-    (((class color) (background dark))
-     (:foreground "red"))
-    (t (:foreground "red")))
-  "Face for JavaScript errors."
-  :group 'js2-mode)
-
-(defface js2-jsdoc-tag-face
-  '((t :foreground "SlateGray"))
-  "Face used to highlight @whatever tags in jsdoc comments."
-  :group 'js2-mode)
-
-(defface js2-jsdoc-type-face
-  '((t :foreground "SteelBlue"))
-  "Face used to highlight {FooBar} types in jsdoc comments."
-  :group 'js2-mode)
-
-(defface js2-jsdoc-value-face
-  '((t :foreground "PeachPuff3"))
-  "Face used to highlight tag values in jsdoc comments."
-  :group 'js2-mode)
-
-(defface js2-function-param-face
-  '((t :foreground "SeaGreen"))
-  "Face used to highlight function parameters in javascript."
-  :group 'js2-mode)
-
-(defface js2-instance-member-face
-  '((t :foreground "DarkOrchid"))
-  "Face used to highlight instance variables in javascript.
-Not currently used."
-  :group 'js2-mode)
-
-(defface js2-private-member-face
-  '((t :foreground "PeachPuff3"))
-  "Face used to highlight calls to private methods in javascript.
-Not currently used."
-  :group 'js2-mode)
-
-(defface js2-private-function-call-face
-  '((t :foreground "goldenrod"))
-  "Face used to highlight calls to private functions in javascript.
-Not currently used."
-  :group 'js2-mode)
-
-(defface js2-jsdoc-html-tag-name-face
-  (if js2-emacs22
-      '((((class color) (min-colors 88) (background light))
-         (:foreground "rosybrown"))
-        (((class color) (min-colors 8) (background dark))
-         (:foreground "yellow"))
-        (((class color) (min-colors 8) (background light))
-         (:foreground "magenta")))
-    '((((type tty pc) (class color) (background light))
-       (:foreground "magenta"))
-      (((type tty pc) (class color) (background dark))
-       (:foreground "yellow"))
-      (t (:foreground "RosyBrown"))))
-    "Face used to highlight jsdoc html tag names"
-  :group 'js2-mode)
-
-(defface js2-jsdoc-html-tag-delimiter-face
-  (if js2-emacs22
-      '((((class color) (min-colors 88) (background light))
-         (:foreground "dark khaki"))
-        (((class color) (min-colors 8) (background dark))
-         (:foreground "green"))
-        (((class color) (min-colors 8) (background light))
-         (:foreground "green")))
-    '((((type tty pc) (class color) (background light))
-       (:foreground "green"))
-      (((type tty pc) (class color) (background dark))
-       (:foreground "green"))
-      (t (:foreground "dark khaki"))))
-  "Face used to highlight brackets in jsdoc html tags."
-  :group 'js2-mode)
-
-(defface js2-external-variable-face
-  '((t :foreground "orange"))
-  "Face used to highlight assignments to undeclared variables.
-An undeclared variable is any variable not declared with var or let
-in the current scope or any lexically enclosing scope.  If you assign
-to such a variable, then you are either expecting it to originate from
-another file, or you've got a potential bug."
-  :group 'js2-mode)
-
-(defcustom js2-highlight-external-variables t
-  "Non-nil to higlight assignments to undeclared variables."
-  :type 'boolean
-  :group 'js2-mode)
-
-(defvar js2-mode-map
-  (let ((map (make-sparse-keymap))
-        keys)
-    (define-key map [mouse-1] #'js2-mode-show-node)
-    (define-key map "\C-m" #'js2-enter-key)
-    (when js2-rebind-eol-bol-keys
-      (define-key map "\C-a" #'js2-beginning-of-line)
-      (define-key map "\C-e" #'js2-end-of-line))
-    (define-key map "\C-c\C-e" #'js2-mode-hide-element)
-    (define-key map "\C-c\C-s" #'js2-mode-show-element)
-    (define-key map "\C-c\C-a" #'js2-mode-show-all)
-    (define-key map "\C-c\C-f" #'js2-mode-toggle-hide-functions)
-    (define-key map "\C-c\C-t" #'js2-mode-toggle-hide-comments)
-    (define-key map "\C-c\C-o" #'js2-mode-toggle-element)
-    (define-key map "\C-c\C-w" #'js2-mode-toggle-warnings-and-errors)
-    (define-key map (kbd "C-c C-'") #'js2-next-error)
-    ;; also define user's preference for next-error, if available
-    (if (setq keys (where-is-internal #'next-error))
-        (define-key map (car keys) #'js2-next-error))
-    (define-key map (or (car (where-is-internal #'mark-defun))
-                        (kbd "M-C-h"))
-      #'js2-mark-defun)
-    (define-key map (or (car (where-is-internal #'narrow-to-defun))
-                        (kbd "C-x nd"))
-      #'js2-narrow-to-defun)
-    (define-key map [down-mouse-3] #'js2-mouse-3)
-    (when js2-auto-indent-flag
-      (mapc (lambda (key)
-              (define-key map key #'js2-insert-and-indent))
-            js2-electric-keys))
-
-    (define-key map [menu-bar javascript]
-      (cons "JavaScript" (make-sparse-keymap "JavaScript")))
-
-    (define-key map [menu-bar javascript customize-js2-mode]
-      '(menu-item "Customize js2-mode" js2-mode-customize
-                  :help "Customize the behavior of this mode"))
-
-    (define-key map [menu-bar javascript js2-force-refresh]
-      '(menu-item "Force buffer refresh" js2-mode-reset
-                  :help "Re-parse the buffer from scratch"))
-
-    (define-key map [menu-bar javascript separator-2]
-      '("--"))
-
-    (define-key map [menu-bar javascript next-error]
-      '(menu-item "Next warning or error" js2-next-error
-                  :enabled (and js2-mode-ast
-                                (or (js2-ast-root-errors js2-mode-ast)
-                                    (js2-ast-root-warnings js2-mode-ast)))
-                  :help "Move to next warning or error"))
-
-    (define-key map [menu-bar javascript display-errors]
-      '(menu-item "Show errors and warnings" js2-mode-display-warnings-and-errors
-                  :visible (not js2-mode-show-parse-errors)
-                  :help "Turn on display of warnings and errors"))
-
-    (define-key map [menu-bar javascript hide-errors]
-      '(menu-item "Hide errors and warnings" js2-mode-hide-warnings-and-errors
-                  :visible js2-mode-show-parse-errors
-                  :help "Turn off display of warnings and errors"))
-
-    (define-key map [menu-bar javascript separator-1]
-      '("--"))
-
-    (define-key map [menu-bar javascript js2-toggle-function]
-      '(menu-item "Show/collapse element" js2-mode-toggle-element
-                  :help "Hide or show function body or comment"))
-
-    (define-key map [menu-bar javascript show-comments]
-      '(menu-item "Show block comments" js2-mode-toggle-hide-comments
-                  :visible js2-mode-comments-hidden
-                  :help "Expand all hidden block comments"))
-
-    (define-key map [menu-bar javascript hide-comments]
-      '(menu-item "Hide block comments" js2-mode-toggle-hide-comments
-                  :visible (not js2-mode-comments-hidden)
-                  :help "Show block comments as /*...*/"))
-
-    (define-key map [menu-bar javascript show-all-functions]
-      '(menu-item "Show function bodies" js2-mode-toggle-hide-functions
-                  :visible js2-mode-functions-hidden
-                  :help "Expand all hidden function bodies"))
-
-    (define-key map [menu-bar javascript hide-all-functions]
-      '(menu-item "Hide function bodies" js2-mode-toggle-hide-functions
-                  :visible (not js2-mode-functions-hidden)
-                  :help "Show {...} for all top-level function bodies"))
-
-    map)
-  "Keymap used in `js2-mode' buffers.")
-
-(defconst js2-mode-identifier-re "[a-zA-Z_$][a-zA-Z0-9_$]*")
-
-(defvar js2-mode-//-comment-re "^\\(\\s-*\\)//.+"
-  "Matches a //-comment line.  Must be first non-whitespace on line.
-First match-group is the leading whitespace.")
-
-(defvar js2-mode-ast nil "Private variable.")
-(make-variable-buffer-local 'js2-mode-ast)
-
-(defvar js2-mode-hook nil)
-
-(defvar js2-mode-parse-timer nil "Private variable.")
-(make-variable-buffer-local 'js2-mode-parse-timer)
-
-(defvar js2-mode-buffer-dirty-p nil "Private variable.")
-(make-variable-buffer-local 'js2-mode-buffer-dirty-p)
-
-(defvar js2-mode-parsing nil "Private variable.")
-(make-variable-buffer-local 'js2-mode-parsing)
-
-(defvar js2-mode-node-overlay nil)
-(make-variable-buffer-local 'js2-mode-node-overlay)
-
-(defvar js2-mode-show-overlay js2-mode-dev-mode-p
-  "Debug:  Non-nil to highlight AST nodes on mouse-down.")
-
-(defvar js2-mode-fontifications nil "Private variable")
-(make-variable-buffer-local 'js2-mode-fontifications)
-
-(defvar js2-mode-deferred-properties nil "Private variable")
-(make-variable-buffer-local 'js2-mode-deferred-properties)
-
-(defvar js2-imenu-recorder nil "Private variable")
-(make-variable-buffer-local 'js2-imenu-recorder)
-
-(defvar js2-imenu-function-map nil "Private variable")
-(make-variable-buffer-local 'js2-imenu-function-map)
-
-(defvar js2-paragraph-start
-  "\\(@[a-zA-Z]+\\>\\|$\\)")
-
-;; Note that we also set a 'c-in-sws text property in html comments,
-;; so that `c-forward-sws' and `c-backward-sws' work properly.
-(defvar js2-syntactic-ws-start
-  "\\s \\|/[*/]\\|[\n\r]\\|\\\\[\n\r]\\|\\s!\\|<!--\\|^\\s-*-->")
-
-(defvar js2-syntactic-ws-end
-  "\\s \\|[\n\r/]\\|\\s!")
-
-(defvar js2-syntactic-eol
-  (concat "\\s *\\(/\\*[^*\n\r]*"
-          "\\(\\*+[^*\n\r/][^*\n\r]*\\)*"
-          "\\*+/\\s *\\)*"
-          "\\(//\\|/\\*[^*\n\r]*"
-          "\\(\\*+[^*\n\r/][^*\n\r]*\\)*$"
-          "\\|\\\\$\\|$\\)")
-  "Copied from java-mode.  Needed for some cc-engine functions.")
-
-(defvar js2-comment-prefix-regexp
-  "//+\\|\\**")
-
-(defvar js2-comment-start-skip
-  "\\(//+\\|/\\*+\\)\\s *")
-
-(defvar js2-mode-verbose-parse-p js2-mode-dev-mode-p
-  "Non-nil to emit status messages during parsing.")
-
-(defvar js2-mode-functions-hidden nil "private variable")
-(defvar js2-mode-comments-hidden nil "private variable")
-
-(defvar js2-mode-syntax-table
-  (let ((table (make-syntax-table)))
-    (c-populate-syntax-table table)
-    table)
-  "Syntax table used in js2-mode buffers.")
-
-(defvar js2-mode-abbrev-table nil
-  "Abbrev table in use in `js2-mode' buffers.")
-(define-abbrev-table 'js2-mode-abbrev-table ())
-
-(defvar js2-mode-must-byte-compile (not js2-mode-dev-mode-p)
-  "Non-nil to have `js2-mode' signal an error if not byte-compiled.")
-
-(defvar js2-mode-pending-parse-callbacks nil
-  "List of functions waiting to be notified that parse is finished.")
-
-(defvar js2-mode-last-indented-line -1)
-
-(eval-when-compile
-  (defvar c-paragraph-start nil)
-  (defvar c-paragraph-separate nil)
-  (defvar c-syntactic-ws-start nil)
-  (defvar c-syntactic-ws-end nil)
-  (defvar c-syntactic-eol nil)
-  (defvar running-xemacs nil)
-  (defvar font-lock-mode nil)
-  (defvar font-lock-keywords nil))
-
-(eval-when-compile
-  (if (< emacs-major-version 22)
-      (defun c-setup-paragraph-variables () nil)))
-
-(provide 'js2-vars)
-
-;;; js2-vars.el ends here
-;;; js2-util.el -- JavaScript utilities
-
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Keywords:  javascript languages
-
-;;; Code
-
-(eval-when-compile
-  (require 'cl))
-
-
-;; Emacs21 compatibility, plus some stuff to avoid runtime dependency on CL
-
-(unless (fboundp #'looking-back)
-  (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."
-    (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)))))
-
-(unless (fboundp #'copy-overlay)
-  (defun copy-overlay (o)
-    "Return a copy of overlay O."
-    (let ((o1 (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)))
-          (props (overlay-properties o)))
-      (while props
-        (overlay-put o1 (pop props) (pop props)))
-      o1)))
-
-(unless (fboundp #'remove-overlays)
-  (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."
-    (unless beg (setq beg (point-min)))
-    (unless end (setq end (point-max)))
-    (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))))))))
-
-;; we don't want a runtime dependency on the CL package, so define
-;; our own versions of these functions.
-
-(defun js2-delete-if (predicate list)
-  "Remove all items satisfying PREDICATE in LIST."
-  (loop for item in list
-        if (not (funcall predicate item))
-        collect item))
-
-(defun js2-position (element list)
-  "Find 0-indexed position of ELEMENT in LIST comparing with `eq'.
-Returns nil if element is not found in the list."
-  (let ((count 0)
-        found)
-    (while (and list (not found))
-      (if (eq element (car list))
-          (setq found t)
-        (setq count (1+ count)
-              list (cdr list))))
-    (if found count)))
-
-(defun js2-find-if (predicate list)
-  "Find first item satisfying PREDICATE in LIST."
-  (let (result)
-    (while (and list (not result))
-      (if (funcall predicate (car list))
-          (setq result (car list)))
-      (setq list (cdr list)))
-    result))
-
-;;; end Emacs 21 compat
-
-(defmacro js2-time (form)
-  "Evaluate FORM, discard result, and return elapsed time in sec"
-  (let ((beg (make-symbol "--js2-time-beg--"))
-        (delta (make-symbol "--js2-time-end--")))
-    `(let ((,beg (current-time))
-           ,delta)
-       ,form
-       (/ (truncate (* (- (float-time (current-time))
-                          (float-time ,beg)))
-                    10000)
-          10000.0))))
-
-(def-edebug-spec js2-time t)
-
-(defsubst neq (expr1 expr2)
-  "Return (not (eq expr1 expr2))."
-  (not (eq expr1 expr2)))
-
-(defsubst js2-same-line (pos)
-  "Return t if POS is on the same line as current point."
-  (and (>= pos (point-at-bol))
-       (<= pos (point-at-eol))))
-
-(defsubst js2-same-line-2 (p1 p2)
-  "Return t if p1 is on the same line as p2."
-  (save-excursion
-    (goto-char p1)
-    (js2-same-line p2)))
-
-(defun js2-code-bug ()
-  "Signal an error when we encounter an unexpected code path."
-  (error "failed assertion"))
-
-;; I'd like to associate errors with nodes, but for now the
-;; easiest thing to do is get the context info from the last token.
-(defsubst js2-record-parse-error (msg &optional arg pos len)
-  (push (list (list msg arg)
-              (or pos js2-token-beg)
-              (or len (- js2-token-end js2-token-beg)))
-        js2-parsed-errors))
-
-(defsubst js2-report-error (msg &optional msg-arg pos len)
-  "Signal a syntax error or record a parse error."
-  (if js2-recover-from-parse-errors
-      (js2-record-parse-error msg msg-arg pos len)
-  (signal 'js2-syntax-error
-          (list msg
-                js2-ts-lineno
-                (save-excursion
-                  (goto-char js2-ts-cursor)
-                  (current-column))
-                js2-ts-hit-eof))))
-
-(defsubst js2-report-warning (msg &optional msg-arg pos len)
-  (if js2-compiler-report-warning-as-error
-      (js2-report-error msg msg-arg pos len)
-    (push (list (list msg msg-arg)
-                (or pos js2-token-beg)
-                (or len (- js2-token-end js2-token-beg)))
-          js2-parsed-warnings)))
-
-(defsubst js2-add-strict-warning (msg-id &optional msg-arg beg end)
-  (if js2-compiler-strict-mode
-      (js2-report-warning msg-id msg-arg beg
-                          (and beg end (- end beg)))))
-
-(put 'js2-syntax-error 'error-conditions
-     '(error syntax-error js2-syntax-error))
-(put 'js2-syntax-error 'error-message "Syntax error")
-
-(put 'js2-parse-error 'error-conditions
-     '(error parse-error js2-parse-error))
-(put 'js2-parse-error 'error-message "Parse error")
-
-(defmacro js2-clear-flag (flags flag)
-  `(setq ,flags (logand ,flags (lognot ,flag))))
-
-(defmacro js2-set-flag (flags flag)
-  "Logical-or FLAG into FLAGS."
-  `(setq ,flags (logior ,flags ,flag)))
-
-(defsubst js2-flag-set-p (flags flag)
-  (/= 0 (logand flags flag)))
-
-(defsubst js2-flag-not-set-p (flags flag)
-  (zerop (logand flags flag)))
-
-;; Stolen shamelessly from James Clark's nxml-mode.
-(defmacro js2-with-unmodifying-text-property-changes (&rest body)
-  "Evaluate BODY without any text property changes modifying the buffer.
-Any text properties changes happen as usual but the changes are not treated as
-modifications to the buffer."
-  (let ((modified (make-symbol "modified")))
-    `(let ((,modified (buffer-modified-p))
-	   (inhibit-read-only t)
-	   (inhibit-modification-hooks t)
-	   (buffer-undo-list t)
-	   (deactivate-mark nil)
-	   ;; Apparently these avoid file locking problems.
-	   (buffer-file-name nil)
-	   (buffer-file-truename nil))
-       (unwind-protect
-	   (progn ,@body)
-	 (unless ,modified
-	   (restore-buffer-modified-p nil))))))
-
-(put 'js2-with-unmodifying-text-property-changes 'lisp-indent-function 0)
-(def-edebug-spec js2-with-unmodifying-text-property-changes t)
-
-(defmacro js2-with-underscore-as-word-syntax (&rest body)
-  "Evaluate BODY with the _ character set to be word-syntax."
-  (let ((old-syntax (make-symbol "old-syntax")))
-  `(let ((,old-syntax (string (char-syntax ?_))))
-     (unwind-protect
-         (progn
-           (modify-syntax-entry ?_ "w" js2-mode-syntax-table)
-           ,@body)
-       (modify-syntax-entry ?_ ,old-syntax js2-mode-syntax-table)))))
-
-(put 'js2-with-underscore-as-word-syntax 'lisp-indent-function 0)
-(def-edebug-spec js2-with-underscore-as-word-syntax t)
-
-(defmacro with-buffer (buf form)
-  "Executes FORM in buffer BUF.
-BUF can be a buffer name or a buffer object.
-If the buffer doesn't exist, it's created."
-  `(let ((buffer (gentemp)))
-    (setq buffer
-	  (if (stringp ,buf)
-	      (get-buffer-create ,buf)
-	    ,buf))
-    (save-excursion
-      (set-buffer buffer)
-      ,form)))
-
-(defsubst char-is-uppercase (c)
-  "Return t if C is an uppercase character.
-Handles unicode and latin chars properly."
-  (/= c (downcase c)))
-
-(defsubst char-is-lowercase (c)
-  "Return t if C is an uppercase character.
-Handles unicode and latin chars properly."
-  (/= c (upcase c)))
-
-(put 'with-buffer 'lisp-indent-function 1)
-(def-edebug-spec with-buffer t)
-
-(provide 'js2-util)
-
-;;; js2-util.el ends here
-;;; js2-scan.el --- JavaScript scanner
-
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Keywords:  javascript languages
-
-;;; Commentary:
-
-;; A port of Mozilla Rhino's scanner.
-;; Corresponds to Rhino files Token.java and TokenStream.java.
-
-;;; Code:
-
-
-(eval-when-compile
-  (require 'cl))
-
-(defvar js2-tokens nil
-  "List of all defined token names.")  ; intialized below
-
-(defvar js2-token-names
-  (let* ((names (make-vector js2-num-tokens -1))
-         (case-fold-search nil)  ; only match js2-UPPER_CASE
-         (syms (apropos-internal "^js2-\\(?:[A-Z_]+\\)")))
-    (loop for sym in syms
-          for i from 0
-          do
-          (unless (or (memq sym '(js2-EOF_CHAR js2-ERROR))
-                      (not (boundp sym)))
-            (aset names (symbol-value sym)         ; code, e.g. 152
-                  (substring (symbol-name sym) 4)) ; name, e.g. "LET"
-            (push sym js2-tokens)))
-    names)
-  "Vector mapping int values to token string names, sans `js2-' prefix.")
-
-(defun js2-token-name (tok)
-  "Return a string name for TOK, a token symbol or code.
-Signals an error if it's not a recognized token."
-  (let ((code tok))
-    (if (symbolp tok)
-        (setq code (symbol-value tok)))
-    (if (eq code -1)
-        "ERROR"
-      (if (and (numberp code)
-               (not (minusp code))
-               (< code js2-num-tokens))
-          (aref js2-token-names code)
-        (error "Invalid token: %s" code)))))
-
-(defsubst js2-token-sym (tok)
-  "Return symbol for TOK given its code, e.g. 'js2-LP for code 86."
-  (intern (js2-token-name tok)))
-
-(defvar js2-token-codes
-  (let ((table (make-hash-table :test 'eq :size 256)))
-    (loop for name across js2-token-names
-          for sym = (intern (concat "js2-" name))
-          do
-          (puthash sym (symbol-value sym) table))
-    ;; clean up a few that are "wrong" in Rhino's token codes
-    (puthash 'js2-DELETE js2-DELPROP table)
-    table)
-  "Hashtable mapping token symbols to their bytecodes.")
-
-(defsubst js2-token-code (sym)
-  "Return code for token symbol SYM, e.g. 86 for 'js2-LP."
-  (or (gethash sym js2-token-codes)
-      (error "Invalid token symbol: %s " sym)))  ; signal code bug
-
-(defsubst js2-report-scan-error (msg &optional no-throw beg len)
-  (setq js2-token-end js2-ts-cursor)
-  (js2-report-error msg nil
-                    (or beg js2-token-beg)
-                    (or len (- js2-token-end js2-token-beg)))
-  (unless no-throw
-    (throw 'return js2-ERROR)))
-
-(defsubst js2-get-string-from-buffer ()
-  "Reverse the char accumulator and return it as a string."
-  (setq js2-token-end js2-ts-cursor)
-  (if js2-ts-string-buffer
-      (apply #'string (nreverse js2-ts-string-buffer))
-    ""))
-
-;; TODO:  could potentially avoid a lot of consing by allocating a
-;; char buffer the way Rhino does.
-(defsubst js2-add-to-string (c)
-  (push c js2-ts-string-buffer))
-
-;; Note that when we "read" the end-of-file, we advance js2-ts-cursor
-;; to (1+ (point-max)), which lets the scanner treat end-of-file like
-;; any other character:  when it's not part of the current token, we
-;; unget it, allowing it to be read again by the following call.
-(defsubst js2-unget-char ()
-  (decf js2-ts-cursor))
-
-;; Rhino distinguishes \r and \n line endings.  We don't need to
-;; because we only scan from Emacs buffers, which always use \n.
-(defsubst js2-get-char ()
-  "Read and return the next character from the input buffer.
-Increments `js2-ts-lineno' if the return value is a newline char.
-Updates `js2-ts-cursor' to the point after the returned char.
-Returns `js2-EOF_CHAR' if we hit the end of the buffer.
-Also updates `js2-ts-hit-eof' and `js2-ts-line-start' as needed."
-  (let (c)
-    ;; check for end of buffer
-    (if (>= js2-ts-cursor (point-max))
-        (setq js2-ts-hit-eof t
-              js2-ts-cursor (1+ js2-ts-cursor)
-              c js2-EOF_CHAR)  ; return value
-
-      ;; otherwise read next char
-      (setq c (char-before (incf js2-ts-cursor)))
-
-      ;; if we read a newline, update counters
-      (if (= c ?\n)
-          (setq js2-ts-line-start js2-ts-cursor
-                js2-ts-lineno (1+ js2-ts-lineno)))
-
-      ;; TODO:  skip over format characters
-      c)))
-
-(defsubst js2-read-unicode-escape ()
-  "Read a \\uNNNN sequence from the input.
-Assumes the ?\ and ?u have already been read.
-Returns the unicode character, or nil if it wasn't a valid character.
-Doesn't change the values of any scanner variables."
-  ;; I really wish I knew a better way to do this, but I can't
-  ;; find the Emacs function that takes a 16-bit int and converts
-  ;; it to a Unicode/utf-8 character.  So I basically eval it with (read).
-  ;; Have to first check that it's 4 hex characters or it may stop
-  ;; the read early.
-  (ignore-errors
-    (let ((s (buffer-substring-no-properties js2-ts-cursor
-                                             (+ 4 js2-ts-cursor))))
-      (if (string-match "[a-zA-Z0-9]\\{4\\}" s)
-          (read (concat "?\\u" s))))))
-
-(defsubst js2-match-char (test)
-  "Consume and return next character if it matches TEST, a character.
-Returns nil and consumes nothing if TEST is not the next character."
-  (let ((c (js2-get-char)))
-    (if (eq c test)
-        t
-      (js2-unget-char)
-      nil)))
-
-(defsubst js2-peek-char ()
-  (prog1
-      (js2-get-char)
-    (js2-unget-char)))
-
-(defsubst js2-java-identifier-start-p (c)
-  (or
-   (memq c '(?$ ?_))
-   (char-is-uppercase c)
-   (char-is-lowercase c)))
-
-(defsubst js2-java-identifier-part-p (c)
-  "Implementation of java.lang.Character.isJavaIdentifierPart()"
-  ;; TODO:  make me Unicode-friendly.  See comments above.
-  (or
-   (memq c '(?$ ?_))
-   (char-is-uppercase c)
-   (char-is-lowercase c)
-   (and (>= c ?0) (<= c ?9))))
-
-(defsubst js2-alpha-p (c)
-  ;; Use 'Z' < 'a'
-  (if (<= c ?Z)
-      (<= ?A c)
-    (and (<= ?a c)
-         (<= c ?z))))
-
-(defsubst js2-digit-p (c)
-  (and (<= ?0 c) (<= c ?9)))
-
-(defsubst js2-js-space-p (c)
-  (if (<= c 127)
-      (memq c '(#x20 #x9 #xC #xB))
-    (or
-     (eq c #xA0)
-     ;; TODO:  change this nil to check for Unicode space character
-     nil)))
-
-(defsubst js2-skip-line ()
-  "Skip to end of line"
-  (let (c)
-    (while (and (/= js2-EOF_CHAR (setq c (js2-get-char)))
-                (/= c ?\n)))
-    (js2-unget-char)
-    (setq js2-token-end js2-ts-cursor)))
-
-(defun js2-init-scanner (&optional buf line)
-  "Create token stream for BUF starting on LINE.
-BUF defaults to current-buffer and line defaults to 1.
-
-A buffer can only have one scanner active at a time, which yields
-dramatically simpler code than using a defstruct.  If you need to
-have simultaneous scanners in a buffer, copy the regions to scan
-into temp buffers."
-  (save-excursion
-    (when buf
-      (set-buffer buf))
-    (setq js2-ts-dirty-line nil
-          js2-ts-regexp-flags nil
-          js2-ts-string ""
-          js2-ts-number nil
-          js2-ts-hit-eof nil
-          js2-ts-line-start 0
-          js2-ts-lineno (or line 1)
-          js2-ts-line-end-char -1
-          js2-ts-cursor (point-min)
-          js2-ts-is-xml-attribute nil
-          js2-ts-xml-is-tag-content nil
-          js2-ts-xml-open-tags-count 0
-          js2-ts-string-buffer nil)))
-
-;; This function uses the cached op, string and number fields in
-;; TokenStream; if getToken has been called since the passed token
-;; was scanned, the op or string printed may be incorrect.
-(defun js2-token-to-string (token)
-  ;; Not sure where this function is used in Rhino.  Not tested.
-  (if (not js2-debug-print-trees)
-      ""
-    (let ((name (js2-token-name token)))
-      (cond
-       ((memq token (list js2-STRING js2-REGEXP js2-NAME))
-        (concat name " `" js2-ts-string "'"))
-       ((eq token js2-NUMBER)
-        (format "NUMBER %g" js2-ts-number))
-       (t
-        name)))))
-
-(defconst js2-keywords
-  '(break
-    case catch const continue
-    debugger default delete do
-    else enum
-    false finally for function
-    if in instanceof import
-    let
-    new null
-    return
-    switch
-    this throw true try typeof
-    var void
-    while with
-    yield))
-
-;; Token names aren't exactly the same as the keywords, unfortunately.
-;; E.g. enum isn't in the tokens, and delete is js2-DELPROP.
-(defconst js2-kwd-tokens
-  (let ((table (make-vector js2-num-tokens nil))
-        (tokens
-         (list js2-BREAK
-               js2-CASE js2-CATCH js2-CONST js2-CONTINUE
-               js2-DEBUGGER js2-DEFAULT js2-DELPROP js2-DO
-               js2-ELSE
-               js2-FALSE js2-FINALLY js2-FOR js2-FUNCTION
-               js2-IF js2-IN js2-INSTANCEOF js2-IMPORT
-               js2-LET
-               js2-NEW js2-NULL
-               js2-RETURN
-               js2-SWITCH
-               js2-THIS js2-THROW js2-TRUE js2-TRY js2-TYPEOF
-               js2-VAR
-               js2-WHILE js2-WITH
-               js2-YIELD)))
-    (dolist (i tokens)
-      (aset table i 'font-lock-keyword-face))
-    (aset table js2-STRING 'font-lock-string-face)
-    (aset table js2-REGEXP 'font-lock-string-face)
-    (aset table js2-COMMENT 'font-lock-comment-face)
-    (aset table js2-THIS 'font-lock-builtin-face)
-    (aset table js2-VOID 'font-lock-constant-face)
-    (aset table js2-NULL 'font-lock-constant-face)
-    (aset table js2-TRUE 'font-lock-constant-face)
-    (aset table js2-FALSE 'font-lock-constant-face)
-    table)
-  "Vector whose values are non-nil for tokens that are keywords.
-The values are default faces to use for highlighting the keywords.")
-
-(defconst js2-reserved-words
-  '(abstract
-    boolean byte
-    char class
-    double
-    enum extends
-    final float
-    goto
-    implements int interface
-    long
-    native
-    package private protected public
-    short static super synchronized
-    throws transient
-    volatile))
-
-(defconst js2-keyword-names
-  (let ((table (make-hash-table :test 'equal)))
-    (loop for k in js2-keywords
-          do (puthash
-              (symbol-name k)                            ; instanceof
-              (intern (concat "js2-"
-                              (upcase (symbol-name k)))) ; js2-INSTANCEOF
-              table))
-    table)
-  "JavaScript keywords by name, mapped to their symbols.")
-
-(defconst js2-reserved-word-names
-  (let ((table (make-hash-table :test 'equal)))
-    (loop for k in js2-reserved-words
-          do
-          (puthash (symbol-name k) 'js2-RESERVED table))
-    table)
-  "JavaScript reserved words by name, mapped to 'js2-RESERVED.")
-
-(defsubst js2-collect-string (buf)
-  "Convert BUF, a list of chars, to a string.
-Reverses BUF before converting."
-  (cond
-   ((stringp buf)
-    buf)
-   ((null buf)  ; for emacs21 compat
-    "")
-   (t
-    (if buf
-        (apply #'string (nreverse buf))
-      ""))))
-
-(defun js2-string-to-keyword (s)
-  "Return token for S, a string, if S is a keyword or reserved word.
-Returns a symbol such as 'js2-BREAK, or nil if not keyword/reserved."
-  (or (gethash s js2-keyword-names)
-      (gethash s js2-reserved-word-names)))
-
-(defsubst js2-ts-set-char-token-bounds ()
-  "Used when next token is one character."
-  (setq js2-token-beg (1- js2-ts-cursor)
-        js2-token-end js2-ts-cursor))
-
-(defsubst js2-ts-return (token)
-  "Return an N-character TOKEN from `js2-get-token'.
-Updates `js2-token-end' accordingly."
-  (setq js2-token-end js2-ts-cursor)
-  (throw 'return token))
-
-(defsubst js2-x-digit-to-int (c accumulator)
-  "Build up a hex number.
-If C is a hexadecimal digit, return ACCUMULATOR * 16 plus
-corresponding number.  Otherwise return -1."
-  (catch 'return
-    (catch 'check
-      ;; Use 0..9 < A..Z < a..z
-      (cond
-       ((<= c ?9)
-        (decf c ?0)
-        (if (<= 0 c)
-            (throw 'check nil)))
-       ((<= c ?F)
-        (when (<= ?A c)
-          (decf c (- ?A 10))
-          (throw 'check nil)))
-       ((<= c ?f)
-        (when (<= ?a c)
-          (decf c (- ?a 10))
-          (throw 'check nil))))
-      (throw 'return -1))
-    (logior c (lsh accumulator 4))))
-
-(defun js2-get-token ()
-  "Return next JavaScript token, an int such as js2-RETURN."
-  (let (c
-        c1
-        identifier-start
-        is-unicode-escape-start
-        contains-escape
-        escape-val
-        escape-start
-        str
-        result
-        base
-        is-integer
-        quote-char
-        val
-        look-for-slash
-        continue)
-    (catch 'return
-      (while t
-        ;; Eat whitespace, possibly sensitive to newlines.
-        (setq continue t)
-        (while continue
-          (setq c (js2-get-char))
-          (cond
-           ((eq c js2-EOF_CHAR)
-            (js2-ts-set-char-token-bounds)
-            (throw 'return js2-EOF))
-           ((eq c ?\n)
-            (js2-ts-set-char-token-bounds)
-            (setq js2-ts-dirty-line nil)
-            (throw 'return js2-EOL))
-           ((not (js2-js-space-p c))
-            (if (/= c ?-)               ; in case end of HTML comment
-                (setq js2-ts-dirty-line t))
-            (setq continue nil))))
-
-        ;; Assume the token will be 1 char - fixed up below.
-        (js2-ts-set-char-token-bounds)
-
-        (when (eq c ?@)
-          (throw 'return js2-XMLATTR))
-
-        ;; identifier/keyword/instanceof?
-        ;; watch out for starting with a <backslash>
-        (cond
-         ((eq c ?\\)
-          (setq c (js2-get-char))
-          (if (eq c ?u)
-              (setq identifier-start t
-                    is-unicode-escape-start t
-                    js2-ts-string-buffer nil)
-            (setq identifier-start nil)
-            (js2-unget-char)
-            (setq c ?\\)))
-         (t
-          (when (setq identifier-start (js2-java-identifier-start-p c))
-            (setq js2-ts-string-buffer nil)
-            (js2-add-to-string c))))
-
-        (when identifier-start
-          (setq contains-escape is-unicode-escape-start)
-          (catch 'break
-            (while t
-              (if is-unicode-escape-start
-                  ;; strictly speaking we should probably push-back
-                  ;; all the bad characters if the <backslash>uXXXX
-                  ;; sequence is malformed. But since there isn't a
-                  ;; correct context(is there?) for a bad Unicode
-                  ;; escape sequence in an identifier, we can report
-                  ;; an error here.
-                  (progn
-                    (setq escape-val 0)
-                    (dotimes (i 4)
-                      (setq c (js2-get-char)
-                            escape-val (js2-x-digit-to-int c escape-val))
-                      ;; Next check takes care of c < 0 and bad escape
-                      (if (minusp escape-val)
-                          (throw 'break nil)))
-                    (if (minusp escape-val)
-                        (js2-report-scan-error "msg.invalid.escape" t))
-                    (js2-add-to-string escape-val)
-                    (setq is-unicode-escape-start nil))
-                (setq c (js2-get-char))
-                (cond
-                 ((eq c ?\\)
-                  (setq c (js2-get-char))
-                  (if (eq c ?u)
-                      (setq is-unicode-escape-start t
-                            contains-escape t)
-                    (js2-report-scan-error "msg.illegal.character" t)))
-                 (t
-                  (if (or (eq c js2-EOF_CHAR)
-                          (not (js2-java-identifier-part-p c)))
-                      (throw 'break nil))
-                  (js2-add-to-string c))))))
-          (js2-unget-char)
-
-          (setq str (js2-get-string-from-buffer))
-          (unless contains-escape
-            ;; OPT we shouldn't have to make a string (object!) to
-            ;; check if it's a keyword.
-
-            ;; Return the corresponding token if it's a keyword
-            (when (setq result (js2-string-to-keyword str))
-              (if (and (< js2-language-version 170)
-                       (memq result '(js2-LET js2-YIELD)))
-                  ;; LET and YIELD are tokens only in 1.7 and later
-                  (setq result 'js2-NAME))
-              (if (neq result js2-RESERVED)
-                  (throw 'return (js2-token-code result)))
-              (js2-report-warning "msg.reserved.keyword" str)))
-
-          ;; If we want to intern these as Rhino does, just use (intern str)
-          (setq js2-ts-string str)
-          (throw 'return js2-NAME))     ; end identifier/kwd check
-
-        ;; is it a number?
-        (when (or (js2-digit-p c)
-                  (and (eq c ?.) (js2-digit-p (js2-peek-char))))
-          (setq js2-ts-string-buffer nil
-                base 10)
-          (when (eq c ?0)
-            (setq c (js2-get-char))
-            (cond
-             ((or (eq c ?x) (eq c ?X))
-              (setq base 16)
-              (setq c (js2-get-char)))
-             ((js2-digit-p c)
-              (setq base 8))
-             (t
-              (js2-add-to-string ?0))))
-
-          (if (eq base 16)
-              (while (<= 0 (js2-x-digit-to-int c 0))
-                (js2-add-to-string c)
-                (setq c (js2-get-char)))
-            (while (and (<= ?0 c) (<= c ?9))
-              ;; We permit 08 and 09 as decimal numbers, which
-              ;; makes our behavior a superset of the ECMA
-              ;; numeric grammar.  We might not always be so
-              ;; permissive, so we warn about it.
-              (when (and (eq base 8) (>= c ?8))
-                (js2-report-warning "msg.bad.octal.literal"
-                                    (if (eq c ?8) "8" "9"))
-                (setq base 10))
-              (js2-add-to-string c)
-              (setq c (js2-get-char))))
-
-          (setq is-integer t)
-
-          (when (and (eq base 10) (memq c '(?. ?e ?E)))
-            (setq is-integer nil)
-            (when (eq c ?.)
-              (loop do
-                    (js2-add-to-string c)
-                    (setq c (js2-get-char))
-                    while (js2-digit-p c)))
-            (when (memq c '(?e ?E))
-              (js2-add-to-string c)
-              (setq c (js2-get-char))
-              (when (memq c '(?+ ?-))
-                (js2-add-to-string c)
-                (setq c (js2-get-char)))
-              (unless (js2-digit-p c)
-                (js2-report-scan-error "msg.missing.exponent" t))
-              (loop do
-                    (js2-add-to-string c)
-                    (setq c (js2-get-char))
-                    while (js2-digit-p c))))
-
-          (js2-unget-char)
-          (setq js2-ts-string (js2-get-string-from-buffer)
-                js2-ts-number
-                (if (and (eq base 10) (not is-integer))
-                    (string-to-number js2-ts-string)
-                  ;; TODO:  call runtime number-parser.  Some of it is in
-                  ;; js2-util.el, but I need to port ScriptRuntime.stringToNumber.
-                  (string-to-number js2-ts-string)))
-          (throw 'return js2-NUMBER))
-
-        ;; is it a string?
-        (when (memq c '(?\" ?\'))
-          ;; We attempt to accumulate a string the fast way, by
-          ;; building it directly out of the reader.  But if there
-          ;; are any escaped characters in the string, we revert to
-          ;; building it out of a string buffer.
-          (setq quote-char c
-                js2-ts-string-buffer nil
-                c (js2-get-char))
-          (catch 'break
-            (while (/= c quote-char)
-              (catch 'continue
-                (when (or (eq c ?\n) (eq c js2-EOF_CHAR))
-                  (js2-unget-char)
-                  (setq js2-token-end js2-ts-cursor)
-                  (js2-report-error "msg.unterminated.string.lit")
-                  (throw 'return js2-STRING))
-
-                (when (eq c ?\\)
-                  ;; We've hit an escaped character
-                  (setq c (js2-get-char))
-                  (case c
-                    (?b (setq c ?\b))
-                    (?f (setq c ?\f))
-                    (?n (setq c ?\n))
-                    (?r (setq c ?\r))
-                    (?t (setq c ?\t))
-                    (?v (setq c ?\v))
-                    (?u
-                     (setq c1 (js2-read-unicode-escape))
-                     (if js2-parse-ide-mode
-                         (if c1
-                             (progn
-                               ;; just copy the string in IDE-mode
-                               (js2-add-to-string ?\\)
-                               (js2-add-to-string ?u)
-                               (dotimes (i 3)
-                                 (js2-add-to-string (js2-get-char)))
-                               (setq c (js2-get-char))) ; added at end of loop
-                           ;; flag it as an invalid escape
-                           (js2-report-warning "msg.invalid.escape"
-                                               nil (- js2-ts-cursor 2) 6))
-                       ;; Get 4 hex digits; if the u escape is not
-                       ;; followed by 4 hex digits, use 'u' + the
-                       ;; literal character sequence that follows.
-                       (js2-add-to-string ?u)
-                       (setq escape-val 0)
-                       (dotimes (i 4)
-                         (setq c (js2-get-char)
-                               escape-val (js2-x-digit-to-int c escape-val))
-                         (if (minusp escape-val)
-                             (throw 'continue nil))
-                         (js2-add-to-string c))
-                       ;; prepare for replace of stored 'u' sequence by escape value
-                       (setq js2-ts-string-buffer (nthcdr 5 js2-ts-string-buffer)
-                             c escape-val)))
-                    (?x
-                     ;; Get 2 hex digits, defaulting to 'x'+literal
-                     ;; sequence, as above.
-                     (setq c (js2-get-char)
-                           escape-val (js2-x-digit-to-int c 0))
-                     (if (minusp escape-val)
-                         (progn
-                           (js2-add-to-string ?x)
-                           (throw 'continue nil))
-                       (setq c1 c
-                             c (js2-get-char)
-                             escape-val (js2-x-digit-to-int c escape-val))
-                       (if (minusp escape-val)
-                           (progn
-                             (js2-add-to-string ?x)
-                             (js2-add-to-string c1)
-                             (throw 'continue nil))
-                         ;; got 2 hex digits
-                         (setq c escape-val))))
-                    (?\n
-                     ;; Remove line terminator after escape to follow
-                     ;; SpiderMonkey and C/C++
-                     (setq c (js2-get-char))
-                     (throw 'continue nil))
-                    (t
-                     (when (and (<= ?0 c) (< c ?8))
-                       (setq val (- c ?0)
-                             c (js2-get-char))
-                       (when (and (<= ?0 c) (< c ?8))
-                         (setq val (- (+ (* 8 val) c) ?0)
-                               c (js2-get-char))
-                         (when (and (<= ?0 c)
-                                    (< c ?8)
-                                    (< val #o37))
-                           ;; c is 3rd char of octal sequence only
-                           ;; if the resulting val <= 0377
-                           (setq val (- (+ (* 8 val) c) ?0)
-                                 c (js2-get-char))))
-                       (js2-unget-char)
-                       (setq c val)))))
-                (js2-add-to-string c)
-                (setq c (js2-get-char)))))
-          (setq js2-ts-string (js2-get-string-from-buffer))
-          (throw 'return js2-STRING))
-
-        (case c
-          (?\;
-           (throw 'return js2-SEMI))
-          (?\[
-           (throw 'return js2-LB))
-          (?\]
-           (throw 'return js2-RB))
-          (?{
-           (throw 'return js2-LC))
-          (?}
-           (throw 'return js2-RC))
-          (?\(
-           (throw 'return js2-LP))
-          (?\)
-           (throw 'return js2-RP))
-          (?,
-           (throw 'return js2-COMMA))
-          (??
-           (throw 'return js2-HOOK))
-          (?:
-           (if (js2-match-char ?:)
-               (js2-ts-return js2-COLONCOLON)
-             (throw 'return js2-COLON)))
-          (?.
-           (if (js2-match-char ?.)
-               (js2-ts-return js2-DOTDOT)
-             (if (js2-match-char ?\()
-                 (js2-ts-return js2-DOTQUERY)
-               (throw 'return js2-DOT))))
-          (?|
-           (if (js2-match-char ?|)
-               (throw 'return js2-OR)
-             (if (js2-match-char ?=)
-                 (js2-ts-return js2-ASSIGN_BITOR)
-               (throw 'return js2-BITOR))))
-          (?^
-           (if (js2-match-char ?=)
-               (js2-ts-return js2-ASSIGN_BITOR)
-             (throw 'return js2-BITXOR)))
-          (?&
-           (if (js2-match-char ?&)
-               (throw 'return js2-AND)
-             (if (js2-match-char ?=)
-                 (js2-ts-return js2-ASSIGN_BITAND)
-               (throw 'return js2-BITAND))))
-          (?=
-           (if (js2-match-char ?=)
-               (if (js2-match-char ?=)
-                   (js2-ts-return js2-SHEQ)
-                 (throw 'return js2-EQ))
-             (throw 'return js2-ASSIGN)))
-          (?!
-           (if (js2-match-char ?=)
-               (if (js2-match-char ?=)
-                   (js2-ts-return js2-SHNE)
-                 (js2-ts-return js2-NE))
-             (throw 'return js2-NOT)))
-          (?<
-           ;; NB:treat HTML begin-comment as comment-till-eol
-           (when (js2-match-char ?!)
-             (when (js2-match-char ?-)
-               (when (js2-match-char ?-)
-                 (js2-skip-line)
-                 (setq js2-ts-comment-type 'html)
-                 (throw 'return js2-COMMENT)))
-             (js2-unget-char))
-
-           (if (js2-match-char ?<)
-               (if (js2-match-char ?=)
-                   (js2-ts-return js2-ASSIGN_LSH)
-                 (js2-ts-return js2-LSH))
-             (if (js2-match-char ?=)
-                 (js2-ts-return js2-LE)
-               (throw 'return js2-LT))))
-          (?>
-           (if (js2-match-char ?>)
-               (if (js2-match-char ?>)
-                   (if (js2-match-char ?=)
-                       (js2-ts-return js2-ASSIGN_URSH)
-                     (js2-ts-return js2-URSH))
-                 (if (js2-match-char ?=)
-                     (js2-ts-return js2-ASSIGN_RSH)
-                   (js2-ts-return js2-RSH)))
-             (if (js2-match-char ?=)
-                 (js2-ts-return js2-GE)
-               (throw 'return js2-GT))))
-          (?*
-           (if (js2-match-char ?=)
-               (js2-ts-return js2-ASSIGN_MUL)
-             (throw 'return js2-MUL)))
-
-          (?/
-           ;; is it a // comment?
-           (when (js2-match-char ?/)
-             (setq js2-token-beg (- js2-ts-cursor 2))
-             (js2-skip-line)
-             (setq js2-ts-comment-type 'line)
-             (throw 'return js2-COMMENT))
-
-           ;; is it a /* comment?
-           (when (js2-match-char ?*)
-             (setq look-for-slash nil
-                   js2-token-beg (- js2-ts-cursor 2)
-                   js2-ts-comment-type
-                   (if (js2-match-char ?*)
-                       (progn
-                         (setq look-for-slash t)
-                         'jsdoc)
-                     'block))
-             (while t
-               (setq c (js2-get-char))
-               (cond
-                ((eq c js2-EOF_CHAR)
-                 (setq js2-token-end (1- js2-ts-cursor))
-                 (js2-report-error "msg.unterminated.comment")
-                 (throw 'return js2-COMMENT))
-                ((eq c ?*)
-                 (setq look-for-slash t))
-                ((eq c ?/)
-                 (if look-for-slash
-                   (js2-ts-return js2-COMMENT)))
-                (t
-                 (setq look-for-slash nil
-                       js2-token-end js2-ts-cursor)))))
-
-           (if (js2-match-char ?=)
-               (js2-ts-return js2-ASSIGN_DIV)
-             (throw 'return js2-DIV)))
-
-           (?#
-            (when js2-skip-preprocessor-directives
-              (js2-skip-line)
-              (setq js2-ts-comment-type 'preprocessor
-                    js2-token-end js2-ts-cursor)
-              (throw 'return js2-COMMENT))
-            (throw 'return js2-ERROR))
-
-          (?%
-           (if (js2-match-char ?=)
-               (js2-ts-return js2-ASSIGN_MOD)
-             (throw 'return js2-MOD)))
-          (?~
-           (throw 'return js2-BITNOT))
-          (?+
-           (if (js2-match-char ?=)
-               (js2-ts-return js2-ASSIGN_ADD)
-             (if (js2-match-char ?+)
-                 (js2-ts-return js2-INC)
-               (throw 'return js2-ADD))))
-          (?-
-           (cond
-            ((js2-match-char ?=)
-             (setq c js2-ASSIGN_SUB))
-            ((js2-match-char ?-)
-             (unless js2-ts-dirty-line
-               ;; treat HTML end-comment after possible whitespace
-               ;; after line start as comment-until-eol
-               (when (js2-match-char ?>)
-                 (js2-skip-line)
-                 (setq js2-ts-comment-type 'html)
-                 (throw 'return js2-COMMENT)))
-             (setq c js2-DEC))
-            (t
-             (setq c js2-SUB)))
-           (setq js2-ts-dirty-line t)
-           (js2-ts-return c))
-
-          (otherwise
-           (js2-report-scan-error "msg.illegal.character")))))))
-
-(defun js2-read-regexp (start-token)
-  "Called by parser when it gets / or /= in literal context."
-  (let (c
-        err
-        in-class  ; inside a '[' .. ']' character-class
-        flags
-        (continue t))
-    (setq js2-token-beg js2-ts-cursor
-          js2-ts-string-buffer nil
-          js2-ts-regexp-flags nil)
-
-    (if (eq start-token js2-ASSIGN_DIV)
-        ;; mis-scanned /=
-        (js2-add-to-string ?=)
-      (if (neq start-token js2-DIV)
-          (error "failed assertion")))
-
-    (while (and (not err)
-                (or (/= (setq c (js2-get-char)) ?/)
-                    in-class))
-      (cond
-       ((or (= c ?\n)
-            (= c js2-EOF_CHAR))
-        (setq js2-token-end (1- js2-ts-cursor)
-              err t
-              js2-ts-string (js2-collect-string js2-ts-string-buffer))
-        (js2-report-error "msg.unterminated.re.lit"))
-       (t (cond
-           ((= c ?\\)
-            (js2-add-to-string c)
-            (setq c (js2-get-char)))
-
-           ((= c ?\[)
-            (setq in-class t))
-
-           ((= c ?\])
-            (setq in-class nil)))
-          (js2-add-to-string c))))
-
-    (unless err
-      (while continue
-        (cond
-         ((js2-match-char ?g)
-          (push ?g flags))
-         ((js2-match-char ?i)
-          (push ?i flags))
-         ((js2-match-char ?m)
-          (push ?m flags))
-         (t
-          (setq continue nil))))
-      (if (js2-alpha-p (js2-peek-char))
-          (js2-report-scan-error "msg.invalid.re.flag" t
-                                 js2-ts-cursor 1))
-      (setq js2-ts-string (js2-collect-string js2-ts-string-buffer)
-            js2-ts-regexp-flags (js2-collect-string flags)
-            js2-token-end js2-ts-cursor)
-      ;; tell `parse-partial-sexp' to ignore this range of chars
-      (put-text-property js2-token-beg js2-token-end 'syntax-class '(2)))))
-
-(defun js2-get-first-xml-token ()
-  (setq js2-ts-xml-open-tags-count 0
-        js2-ts-is-xml-attribute nil
-        js2-ts-xml-is-tag-content nil)
-  (js2-unget-char)
-  (js2-get-next-xml-token))
-
-(defsubst js2-xml-discard-string ()
-  "Throw away the string in progress and flag an XML parse error."
-  (setq js2-ts-string-buffer nil
-        js2-ts-string nil)
-  (js2-report-scan-error "msg.XML.bad.form" t))
-
-(defun js2-get-next-xml-token ()
-  (setq js2-ts-string-buffer nil  ; for recording the XML
-        js2-token-beg js2-ts-cursor)
-  (let (c result)
-    (setq result
-          (catch 'return
-            (while t
-              (setq c (js2-get-char))
-              (cond
-               ((= c js2-EOF_CHAR)
-                (throw 'return js2-ERROR))
-
-               (js2-ts-xml-is-tag-content
-                (case c
-                  (?>
-                   (js2-add-to-string c)
-                   (setq js2-ts-xml-is-tag-content nil
-                         js2-ts-is-xml-attribute nil))
-                  (?/
-                   (js2-add-to-string c)
-                   (when (eq ?> (js2-peek-char))
-                     (setq c (js2-get-char))
-                     (js2-add-to-string c)
-                     (setq js2-ts-xml-is-tag-content nil)
-                     (decf js2-ts-xml-open-tags-count)))
-                  (?{
-                   (js2-unget-char)
-                   (setq js2-ts-string (js2-get-string-from-buffer))
-                   (throw 'return js2-XML))
-                  ((?\' ?\")
-                   (js2-add-to-string c)
-                   (unless (js2-read-quoted-string c)
-                     (throw 'return js2-ERROR)))
-                  (?=
-                   (js2-add-to-string c)
-                   (setq js2-ts-is-xml-attribute t))
-                  ((? ?\t ?\r ?\n)
-                   (js2-add-to-string c))
-                  (t
-                   (js2-add-to-string c)
-                   (setq js2-ts-is-xml-attribute nil)))
-                (when (and (not js2-ts-xml-is-tag-content)
-                           (zerop js2-ts-xml-open-tags-count))
-                  (setq js2-ts-string (js2-get-string-from-buffer))
-                  (throw 'return js2-XMLEND)))
-
-               (t
-                ;; else not tag content
-                (case c
-                  (?<
-                   (js2-add-to-string c)
-                   (setq c (js2-peek-char))
-                   (case c
-                     (?!
-                      (setq c (js2-get-char)) ;; skip !
-                      (js2-add-to-string c)
-                      (setq c (js2-peek-char))
-                      (case c
-                        (?-
-                         (setq c (js2-get-char)) ;; skip -
-                         (js2-add-to-string c)
-                         (if (eq c ?-)
-                             (progn
-                               (js2-add-to-string c)
-                               (unless (js2-read-xml-comment)
-                                 (throw 'return js2-ERROR)))
-                           (js2-xml-discard-string)
-                           (throw 'return js2-ERROR)))
-                        (?\[
-                         (setq c (js2-get-char)) ;; skip [
-                         (js2-add-to-string c)
-                         (if (and (= (js2-get-char) ?C)
-                                  (= (js2-get-char) ?D)
-                                  (= (js2-get-char) ?A)
-                                  (= (js2-get-char) ?T)
-                                  (= (js2-get-char) ?A)
-                                  (= (js2-get-char) ?\[))
-                             (progn
-                               (js2-add-to-string ?C)
-                               (js2-add-to-string ?D)
-                               (js2-add-to-string ?A)
-                               (js2-add-to-string ?T)
-                               (js2-add-to-string ?A)
-                               (js2-add-to-string ?\[)
-                               (unless (js2-read-cdata)
-                                 (throw 'return js2-ERROR)))
-                           (js2-xml-discard-string)
-                           (throw 'return js2-ERROR)))
-                        (t
-                         (unless (js2-read-entity)
-                           (throw 'return js2-ERROR)))))
-                     (??
-                      (setq c (js2-get-char)) ;; skip ?
-                      (js2-add-to-string c)
-                      (unless (js2-read-PI)
-                        (throw 'return js2-ERROR)))
-                     (?/
-                      ;; end tag
-                      (setq c (js2-get-char)) ;; skip /
-                      (js2-add-to-string c)
-                      (when (zerop js2-ts-xml-open-tags-count)
-                        (js2-xml-discard-string)
-                        (throw 'return js2-ERROR))
-                      (setq js2-ts-xml-is-tag-content t)
-                      (decf js2-ts-xml-open-tags-count))
-                     (t
-                      ;; start tag
-                      (setq js2-ts-xml-is-tag-content t)
-                      (incf js2-ts-xml-open-tags-count))))
-                  (?{
-                   (js2-unget-char)
-                   (setq js2-ts-string (js2-get-string-from-buffer))
-                   (throw 'return js2-XML))
-                  (t
-                   (js2-add-to-string c))))))))
-    (setq js2-token-end js2-ts-cursor)
-    result))
-
-(defun js2-read-quoted-string (quote)
-  (let (c)
-    (catch 'return
-      (while (/= (setq c (js2-get-char)) js2-EOF_CHAR)
-        (js2-add-to-string c)
-        (if (eq c quote)
-            (throw 'return t)))
-      (js2-xml-discard-string)  ;; throw away string in progress
-      nil)))
-
-(defun js2-read-xml-comment ()
-  (let ((c (js2-get-char)))
-    (catch 'return
-      (while (/= c js2-EOF_CHAR)
-        (catch 'continue
-          (js2-add-to-string c)
-          (when (and (eq c ?-) (eq ?- (js2-peek-char)))
-            (setq c (js2-get-char))
-            (js2-add-to-string c)
-            (if (eq (js2-peek-char) ?>)
-                (progn
-                  (setq c (js2-get-char)) ;; skip >
-                  (js2-add-to-string c)
-                  (throw 'return t))
-              (throw 'continue nil)))
-          (setq c (js2-get-char))))
-      (js2-xml-discard-string)
-      nil)))
-
-(defun js2-read-cdata ()
-  (let ((c (js2-get-char)))
-    (catch 'return
-      (while (/= c js2-EOF_CHAR)
-        (catch 'continue
-          (js2-add-to-string c)
-          (when (and (eq c ?\]) (eq (js2-peek-char) ?\]))
-            (setq c (js2-get-char))
-            (js2-add-to-string c)
-            (if (eq (js2-peek-char) ?>)
-                (progn
-                  (setq c (js2-get-char)) ;; Skip >
-                  (js2-add-to-string c)
-                  (throw 'return t))
-              (throw 'continue nil)))
-          (setq c (js2-get-char))))
-      (js2-xml-discard-string)
-      nil)))
-
-(defun js2-read-entity ()
-  (let ((decl-tags 1)
-        c)
-    (catch 'return
-      (while (/= js2-EOF_CHAR (setq c (js2-get-char)))
-        (js2-add-to-string c)
-        (case c
-          (?<
-           (incf decl-tags))
-          (?>
-           (decf decl-tags)
-           (if (zerop decl-tags)
-               (throw 'return t)))))
-      (js2-xml-discard-string)
-      nil)))
-
-(defun js2-read-PI ()
-  "Scan an XML processing instruction."
-  (let (c)
-    (catch 'return
-      (while (/= js2-EOF_CHAR (setq c (js2-get-char)))
-        (js2-add-to-string c)
-        (when (and (eq c ??) (eq (js2-peek-char) ?>))
-          (setq c (js2-get-char))  ;; Skip >
-          (js2-add-to-string c)
-          (throw 'return t)))
-      (js2-xml-discard-string)
-      nil)))
-
-(defun js2-scanner-get-line ()
-  "Return the text of the current scan line."
-  (buffer-substring (point-at-bol) (point-at-eol)))
-
-(provide 'js2-scan)
-
-;;; js2-scan.el ends here
-;;; js2-messages:  localizable messages for js2-mode
-
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Keywords:  javascript languages
-
-;;; Commentary:
-
-;; Messages are copied from Rhino's Messages.properties.
-;; Many of the Java-specific messages have been elided.
-;; Add any js2-specific ones at the end, so we can keep
-;; this file synced with changes to Rhino's.
-;;
-;; TODO:
-;;  - move interpreter messages into separate file
-
-;;; Code:
-
-(defvar js2-message-table
-  (make-hash-table :test 'equal :size 250)
-  "Contains localized messages for js2-mode.")
-
-;; TODO:  construct this hashtable at compile-time.
-(defmacro js2-msg (key &rest strings)
-  `(puthash ,key (funcall #'concat ,@strings)
-            js2-message-table))
-
-(defun js2-get-msg (msg-key)
-  "Look up a localized message.
-MSG-KEY is a list of (MSG ARGS).  If the message takes parameters,
-the correct number of ARGS must be provided."
-  (let* ((key (if (listp msg-key) (car msg-key) msg-key))
-         (args (if (listp msg-key) (cdr msg-key)))
-         (msg (gethash key js2-message-table)))
-    (if msg
-        (apply #'format msg args)
-      key)))  ; default to showing the key
-
-(js2-msg "msg.dup.parms"
-         "Duplicate parameter name '%s'.")
-
-(js2-msg "msg.too.big.jump"
-         "Program too complex: jump offset too big.")
-
-(js2-msg "msg.too.big.index"
-         "Program too complex: internal index exceeds 64K limit.")
-
-(js2-msg "msg.while.compiling.fn"
-         "Encountered code generation error while compiling function '%s': %s")
-
-(js2-msg "msg.while.compiling.script"
-         "Encountered code generation error while compiling script: %s")
-
-;; Context
-(js2-msg "msg.ctor.not.found"
-         "Constructor for '%s' not found.")
-
-(js2-msg "msg.not.ctor"
-         "'%s' is not a constructor.")
-
-;; FunctionObject
-(js2-msg "msg.varargs.ctor"
-         "Method or constructor '%s' must be static "
-         "with the signature (Context cx, Object[] args, "
-         "Function ctorObj, boolean inNewExpr) "
-         "to define a variable arguments constructor.")
-
-(js2-msg "msg.varargs.fun"
-         "Method '%s' must be static with the signature "
-         "(Context cx, Scriptable thisObj, Object[] args, Function funObj) "
-         "to define a variable arguments function.")
-
-(js2-msg "msg.incompat.call"
-         "Method '%s' called on incompatible object.")
-
-(js2-msg "msg.bad.parms"
-         "Unsupported parameter type '%s' in method '%s'.")
-
-(js2-msg "msg.bad.method.return"
-         "Unsupported return type '%s' in method '%s'.")
-
-(js2-msg "msg.bad.ctor.return"
-         "Construction of objects of type '%s' is not supported.")
-
-(js2-msg "msg.no.overload"
-         "Method '%s' occurs multiple times in class '%s'.")
-
-(js2-msg "msg.method.not.found"
-         "Method '%s' not found in '%s'.")
-
-;; IRFactory
-
-(js2-msg "msg.bad.for.in.lhs"
-         "Invalid left-hand side of for..in loop.")
-
-(js2-msg "msg.mult.index"
-         "Only one variable allowed in for..in loop.")
-
-(js2-msg "msg.bad.for.in.destruct"
-         "Left hand side of for..in loop must be an array of "
-         "length 2 to accept key/value pair.")
-
-(js2-msg "msg.cant.convert"
-         "Can't convert to type '%s'.")
-
-(js2-msg "msg.bad.assign.left"
-         "Invalid assignment left-hand side.")
-
-(js2-msg "msg.bad.decr"
-         "Invalid decerement operand.")
-
-(js2-msg "msg.bad.incr"
-         "Invalid increment operand.")
-
-(js2-msg "msg.bad.yield"
-         "yield must be in a function.")
-
-(js2-msg "msg.yield.parenthesized"
-         "yield expression must be parenthesized.")
-
-;; NativeGlobal
-(js2-msg "msg.cant.call.indirect"
-          "Function '%s' must be called directly, and not by way of a "
-          "function of another name.")
-
-(js2-msg "msg.eval.nonstring"
-          "Calling eval() with anything other than a primitive "
-          "string value will simply return the value. "
-          "Is this what you intended?")
-
-(js2-msg "msg.eval.nonstring.strict"
-         "Calling eval() with anything other than a primitive "
-         "string value is not allowed in strict mode.")
-
-(js2-msg "msg.bad.destruct.op"
-         "Invalid destructuring assignment operator")
-
-;; NativeCall
-(js2-msg "msg.only.from.new"
-         "'%s' may only be invoked from a `new' expression.")
-
-(js2-msg "msg.deprec.ctor"
-         "The '%s' constructor is deprecated.")
-
-;; NativeFunction
-(js2-msg "msg.no.function.ref.found"
-         "no source found to decompile function reference %s")
-
-(js2-msg "msg.arg.isnt.array"
-         "second argument to Function.prototype.apply must be an array")
-
-;; NativeGlobal
-(js2-msg "msg.bad.esc.mask"
-         "invalid string escape mask")
-
-;; NativeRegExp
-(js2-msg "msg.bad.quant"
-  "Invalid quantifier %s")
-
-(js2-msg "msg.overlarge.backref"
-  "Overly large back reference %s")
-
-(js2-msg "msg.overlarge.min"
-  "Overly large minimum %s")
-
-(js2-msg "msg.overlarge.max"
-  "Overly large maximum %s")
-
-(js2-msg "msg.zero.quant"
-  "Zero quantifier %s")
-
-(js2-msg "msg.max.lt.min"
-  "Maximum %s less than minimum")
-
-(js2-msg "msg.unterm.quant"
-  "Unterminated quantifier %s")
-
-(js2-msg "msg.unterm.paren"
-  "Unterminated parenthetical %s")
-
-(js2-msg "msg.unterm.class"
-  "Unterminated character class %s")
-
-(js2-msg "msg.bad.range"
-  "Invalid range in character class.")
-
-(js2-msg "msg.trail.backslash"
-  "Trailing \\ in regular expression.")
-
-(js2-msg "msg.re.unmatched.right.paren"
-  "unmatched ) in regular expression.")
-
-(js2-msg "msg.no.regexp"
-  "Regular expressions are not available.")
-
-(js2-msg "msg.bad.backref"
-  "back-reference exceeds number of capturing parentheses.")
-
-(js2-msg "msg.bad.regexp.compile"
-         "Only one argument may be specified if the first "
-         "argument to RegExp.prototype.compile is a RegExp object.")
-
-;; Parser
-(js2-msg "msg.got.syntax.errors"
-         "Compilation produced %s syntax errors.")
-
-(js2-msg "msg.var.redecl"
-         "TypeError: redeclaration of var %s.")
-
-(js2-msg "msg.const.redecl"
-         "TypeError: redeclaration of const %s.")
-
-(js2-msg "msg.let.redecl"
-         "TypeError: redeclaration of variable %s.")
-
-(js2-msg "msg.parm.redecl"
-         "TypeError: redeclaration of formal parameter %s.")
-
-(js2-msg "msg.fn.redecl"
-         "TypeError: redeclaration of function %s.")
-
-(js2-msg "msg.let.decl.not.in.block"
-         "SyntaxError: let declaration not directly within block")
-
-;; NodeTransformer
-(js2-msg "msg.dup.label"
-         "duplicated label")
-
-(js2-msg "msg.undef.label"
-         "undefined label")
-
-(js2-msg "msg.bad.break"
-         "unlabelled break must be inside loop or switch")
-
-(js2-msg "msg.continue.outside"
-         "continue must be inside loop")
-
-(js2-msg "msg.continue.nonloop"
-         "continue can only use labels of iteration statements")
-
-(js2-msg "msg.bad.throw.eol"
-         "Line terminator is not allowed between the throw "
-         "keyword and throw expression.")
-
-(js2-msg "msg.no.paren.parms"
-         "missing ( before function parameters.")
-
-(js2-msg "msg.no.parm"
-         "missing formal parameter")
-
-(js2-msg "msg.no.paren.after.parms"
-         "missing ) after formal parameters")
-
-(js2-msg "msg.no.brace.body"
-         "missing '{' before function body")
-
-(js2-msg "msg.no.brace.after.body"
-         "missing } after function body")
-
-(js2-msg "msg.no.paren.cond"
-         "missing ( before condition")
-
-(js2-msg "msg.no.paren.after.cond"
-         "missing ) after condition")
-
-(js2-msg "msg.no.semi.stmt"
-         "missing ; before statement")
-
-(js2-msg "msg.missing.semi"
-         "missing ; after statement")
-
-(js2-msg "msg.no.name.after.dot"
-         "missing name after . operator")
-
-(js2-msg "msg.no.name.after.coloncolon"
-         "missing name after :: operator")
-
-(js2-msg "msg.no.name.after.dotdot"
-         "missing name after .. operator")
-
-(js2-msg "msg.no.name.after.xmlAttr"
-         "missing name after .@")
-
-(js2-msg "msg.no.bracket.index"
-         "missing ] in index expression")
-
-(js2-msg "msg.no.paren.switch"
-         "missing ( before switch expression")
-
-(js2-msg "msg.no.paren.after.switch"
-         "missing ) after switch expression")
-
-(js2-msg "msg.no.brace.switch"
-         "missing '{' before switch body")
-
-(js2-msg "msg.bad.switch"
-         "invalid switch statement")
-
-(js2-msg "msg.no.colon.case"
-         "missing : after case expression")
-
-(js2-msg "msg.double.switch.default"
-         "double default label in the switch statement")
-
-(js2-msg "msg.no.while.do"
-         "missing while after do-loop body")
-
-(js2-msg "msg.no.paren.for"
-         "missing ( after for")
-
-(js2-msg "msg.no.semi.for"
-         "missing ; after for-loop initializer")
-
-(js2-msg "msg.no.semi.for.cond"
-         "missing ; after for-loop condition")
-
-(js2-msg "msg.in.after.for.name"
-         "missing in after for")
-
-(js2-msg "msg.no.paren.for.ctrl"
-         "missing ) after for-loop control")
-
-(js2-msg "msg.no.paren.with"
-         "missing ( before with-statement object")
-
-(js2-msg "msg.no.paren.after.with"
-         "missing ) after with-statement object")
-
-(js2-msg "msg.no.paren.after.let"
-         "missing ( after let")
-
-(js2-msg "msg.no.paren.let"
-         "missing ) after variable list")
-
-(js2-msg "msg.no.curly.let"
-         "missing } after let statement")
-
-(js2-msg "msg.bad.return"
-         "invalid return")
-
-(js2-msg "msg.no.brace.block"
-         "missing } in compound statement")
-
-(js2-msg "msg.bad.label"
-         "invalid label")
-
-(js2-msg "msg.bad.var"
-         "missing variable name")
-
-(js2-msg "msg.bad.var.init"
-         "invalid variable initialization")
-
-(js2-msg "msg.no.colon.cond"
-         "missing : in conditional expression")
-
-(js2-msg "msg.no.paren.arg"
-         "missing ) after argument list")
-
-(js2-msg "msg.no.bracket.arg"
-         "missing ] after element list")
-
-(js2-msg "msg.bad.prop"
-         "invalid property id")
-
-(js2-msg "msg.no.colon.prop"
-         "missing : after property id")
-
-(js2-msg "msg.no.brace.prop"
-         "missing } after property list")
-
-(js2-msg "msg.no.paren"
-         "missing ) in parenthetical")
-
-(js2-msg "msg.reserved.id"
-         "identifier is a reserved word")
-
-(js2-msg "msg.no.paren.catch"
-         "missing ( before catch-block condition")
-
-(js2-msg "msg.bad.catchcond"
-         "invalid catch block condition")
-
-(js2-msg "msg.catch.unreachable"
-         "any catch clauses following an unqualified catch are unreachable")
-
-(js2-msg "msg.no.brace.try"
-         "missing '{' before try block")
-
-(js2-msg "msg.no.brace.catchblock"
-         "missing '{' before catch-block body")
-
-(js2-msg "msg.try.no.catchfinally"
-         "'try' without 'catch' or 'finally'")
-
-(js2-msg "msg.no.return.value"
-         "function %s does not always return a value")
-
-(js2-msg "msg.anon.no.return.value"
-         "anonymous function does not always return a value")
-
-(js2-msg "msg.return.inconsistent"
-         "return statement is inconsistent with previous usage")
-
-(js2-msg "msg.generator.returns"
-         "TypeError: generator function '%s' returns a value")
-
-(js2-msg "msg.anon.generator.returns"
-         "TypeError: anonymous generator function returns a value")
-
-(js2-msg "msg.syntax"
-         "syntax error")
-
-(js2-msg "msg.unexpected.eof"
-         "Unexpected end of file")
-
-(js2-msg "msg.XML.bad.form"
-         "illegally formed XML syntax")
-
-(js2-msg "msg.XML.not.available"
-         "XML runtime not available")
-
-(js2-msg "msg.too.deep.parser.recursion"
-         "Too deep recursion while parsing")
-
-(js2-msg "msg.no.side.effects"
-         "Code has no side effects")
-
-(js2-msg "msg.extra.trailing.comma"
-         "Trailing comma is not legal in an ECMA-262 object initializer")
-
-(js2-msg "msg.array.trailing.comma"
-         "Trailing comma yields different behavior across browsers")
-
-(js2-msg "msg.equal.as.assign"
-         (concat "Test for equality (==) mistyped as assignment (=)?"
-                 " (parenthesize to suppress warning)"))
-
-(js2-msg "msg.var.hides.arg"
-         "Variable %s hides argument")
-
-(js2-msg "msg.destruct.assign.no.init"
-         "Missing = in destructuring declaration")
-
-;; ScriptRuntime
-(js2-msg "msg.no.properties"
-         "%s has no properties.")
-
-(js2-msg "msg.invalid.iterator"
-         "Invalid iterator value")
-
-(js2-msg "msg.iterator.primitive"
-         "__iterator__ returned a primitive value")
-
-(js2-msg "msg.assn.create.strict"
-         "Assignment to undeclared variable %s")
-
-(js2-msg "msg.ref.undefined.prop"
-         "Reference to undefined property '%s'")
-
-(js2-msg "msg.prop.not.found"
-         "Property %s not found.")
-
-(js2-msg "msg.invalid.type"
-         "Invalid JavaScript value of type %s")
-
-(js2-msg "msg.primitive.expected"
-         "Primitive type expected (had %s instead)")
-
-(js2-msg "msg.namespace.expected"
-         "Namespace object expected to left of :: (found %s instead)")
-
-(js2-msg "msg.null.to.object"
-         "Cannot convert null to an object.")
-
-(js2-msg "msg.undef.to.object"
-         "Cannot convert undefined to an object.")
-
-(js2-msg "msg.cyclic.value"
-         "Cyclic %s value not allowed.")
-
-(js2-msg "msg.is.not.defined"
-         "'%s' is not defined.")
-
-(js2-msg "msg.undef.prop.read"
-         "Cannot read property '%s' from %s")
-
-(js2-msg "msg.undef.prop.write"
-         "Cannot set property '%s' of %s to '%s'")
-
-(js2-msg "msg.undef.prop.delete"
-         "Cannot delete property '%s' of %s")
-
-(js2-msg "msg.undef.method.call"
-         "Cannot call method '%s' of %s")
-
-(js2-msg "msg.undef.with"
-         "Cannot apply 'with' to %s")
-
-(js2-msg "msg.isnt.function"
-         "%s is not a function, it is %s.")
-
-(js2-msg "msg.isnt.function.in"
-         "Cannot call property %s in object %s. "
-         "It is not a function, it is '%s'.")
-
-(js2-msg "msg.function.not.found"
-         "Cannot find function %s.")
-
-(js2-msg "msg.function.not.found.in"
-         "Cannot find function %s in object %s.")
-
-(js2-msg "msg.isnt.xml.object"
-         "%s is not an xml object.")
-
-(js2-msg "msg.no.ref.to.get"
-         "%s is not a reference to read reference value.")
-
-(js2-msg "msg.no.ref.to.set"
-         "%s is not a reference to set reference value to %s.")
-
-(js2-msg "msg.no.ref.from.function"
-         "Function %s can not be used as the left-hand "
-         "side of assignment or as an operand of ++ or -- operator.")
-
-(js2-msg "msg.bad.default.value"
-         "Object's getDefaultValue() method returned an object.")
-
-(js2-msg "msg.instanceof.not.object"
-         "Can't use instanceof on a non-object.")
-
-(js2-msg "msg.instanceof.bad.prototype"
-         "'prototype' property of %s is not an object.")
-
-(js2-msg "msg.bad.radix"
-         "illegal radix %s.")
-
-;; ScriptableObject
-(js2-msg "msg.default.value"
-         "Cannot find default value for object.")
-
-(js2-msg "msg.zero.arg.ctor"
-         "Cannot load class '%s' which has no zero-parameter constructor.")
-
-(js2-msg "msg.ctor.multiple.parms"
-         "Can't define constructor or class %s since more than "
-         "one constructor has multiple parameters.")
-
-(js2-msg "msg.extend.scriptable"
-         "%s must extend ScriptableObject in order to define property %s.")
-
-(js2-msg "msg.bad.getter.parms"
-         "In order to define a property, getter %s must have zero "
-         "parameters or a single ScriptableObject parameter.")
-
-(js2-msg "msg.obj.getter.parms"
-         "Expected static or delegated getter %s to take "
-         "a ScriptableObject parameter.")
-
-(js2-msg "msg.getter.static"
-         "Getter and setter must both be static or neither be static.")
-
-(js2-msg "msg.setter.return"
-         "Setter must have void return type: %s")
-
-(js2-msg "msg.setter2.parms"
-         "Two-parameter setter must take a ScriptableObject as "
-         "its first parameter.")
-
-(js2-msg "msg.setter1.parms"
-         "Expected single parameter setter for %s")
-
-(js2-msg "msg.setter2.expected"
-         "Expected static or delegated setter %s to take two parameters.")
-
-(js2-msg "msg.setter.parms"
-         "Expected either one or two parameters for setter.")
-
-(js2-msg "msg.setter.bad.type"
-         "Unsupported parameter type '%s' in setter '%s'.")
-
-(js2-msg "msg.add.sealed"
-         "Cannot add a property to a sealed object: %s.")
-
-(js2-msg "msg.remove.sealed"
-         "Cannot remove a property from a sealed object: %s.")
-
-(js2-msg "msg.modify.sealed"
-         "Cannot modify a property of a sealed object: %s.")
-
-(js2-msg "msg.modify.readonly"
-         "Cannot modify readonly property: %s.")
-
-;; TokenStream
-(js2-msg "msg.missing.exponent"
-         "missing exponent")
-
-(js2-msg "msg.caught.nfe"
-         "number format error")
-
-(js2-msg "msg.unterminated.string.lit"
-         "unterminated string literal")
-
-(js2-msg "msg.unterminated.comment"
-         "unterminated comment")
-
-(js2-msg "msg.unterminated.re.lit"
-         "unterminated regular expression literal")
-
-(js2-msg "msg.invalid.re.flag"
-         "invalid flag after regular expression")
-
-(js2-msg "msg.no.re.input.for"
-         "no input for %s")
-
-(js2-msg "msg.illegal.character"
-         "illegal character")
-
-(js2-msg "msg.invalid.escape"
-         "invalid Unicode escape sequence")
-
-(js2-msg "msg.bad.namespace"
-         "not a valid default namespace statement. "
-         "Syntax is: default xml namespace = EXPRESSION;")
-
-;; TokensStream warnings
-(js2-msg "msg.bad.octal.literal"
-         "illegal octal literal digit %s; "
-         "interpreting it as a decimal digit")
-
-(js2-msg "msg.reserved.keyword"
-         "illegal usage of future reserved keyword %s; "
-         "interpreting it as ordinary identifier")
-
-(js2-msg "msg.script.is.not.constructor"
-         "Script objects are not constructors.")
-
-;; Arrays
-(js2-msg "msg.arraylength.bad"
-         "Inappropriate array length.")
-
-;; Arrays
-(js2-msg "msg.arraylength.too.big"
-         "Array length %s exceeds supported capacity limit.")
-
-;; URI
-(js2-msg "msg.bad.uri"
-         "Malformed URI sequence.")
-
-;; Number
-(js2-msg "msg.bad.precision"
-         "Precision %s out of range.")
-
-;; NativeGenerator
-(js2-msg "msg.send.newborn"
-         "Attempt to send value to newborn generator")
-
-(js2-msg "msg.already.exec.gen"
-         "Already executing generator")
-
-(js2-msg "msg.StopIteration.invalid"
-         "StopIteration may not be changed to an arbitrary object.")
-
-;; Interpreter
-(js2-msg "msg.yield.closing"
-         "Yield from closing generator")
-
-(provide 'js2-messages)
-;;; js2-ast.el --- JavaScript syntax tree node definitions
-
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Keywords:  javascript languages
-
-;;; Code:
-
-(eval-and-compile
-  (require 'cl))
-
-
-;; flags for ast node property 'member-type (used for e4x operators)
-(defvar js2-property-flag    #x1 "property access: element is valid name")
-(defvar js2-attribute-flag   #x2 "x.@y or x..@y")
-(defvar js2-descendants-flag #x4 "x..y or x..@i")
-
-(defsubst js2-relpos (pos anchor)
-  "Convert POS to be relative to ANCHOR.
-If POS is nil, returns nil."
-  (and pos (- pos anchor)))
-
-(defsubst js2-make-pad (indent)
-  (if (zerop indent)
-      ""
-    (make-string (* indent js2-basic-offset) ? )))
-
-(defsubst js2-visit-ast (node callback)
-  "Visit every node in ast NODE with visitor CALLBACK.
-
-CALLBACK is a function that takes two arguments:  (NODE END-P).  It is
-called twice:  once to visit the node, and again after all the node's
-children have been processed.  The END-P argument is nil on the first
-call and non-nil on the second call.  The return value of the callback
-affects the traversal:  if non-nil, the children of NODE are processed.
-If the callback returns nil, or if the node has no children, then the
-callback is called immediately with a non-nil END-P argument.
-
-The node traversal is approximately lexical-order, although there
-are currently no guarantees around this."
-  (let ((vfunc (get (aref node 0) 'js2-visitor)))
-    ;; visit the node
-    (when  (funcall callback node nil)
-      ;; visit the kids
-      (cond
-       ((eq vfunc 'js2-visit-none)
-        nil)                            ; don't even bother calling it
-       ;; Each AST node type has to define a `js2-visitor' function
-       ;; that takes a node and a callback, and calls `js2-visit-ast'
-       ;; on each child of the node.
-       (vfunc
-        (funcall vfunc node callback))
-       (t
-        (error "%s does not define a visitor-traversal function"
-               (aref node 0)))))
-    ;; call the end-visit
-    (funcall callback node t)))
-
-(defstruct (js2-node
-            (:constructor nil))  ; abstract
-  "Base AST node type."
-  (type -1)  ; token type
-  (pos -1)   ; start position of this AST node in parsed input
-  (len 1)    ; num characters spanned by the node
-  props      ; optional node property list (an alist)
-  parent)    ; link to parent node; null for root
-
-(defsubst js2-node-get-prop (node prop &optional default)
-  (or (cadr (assoc prop (js2-node-props node))) default))
-
-(defsubst js2-node-set-prop (node prop value)
-  (setf (js2-node-props node)
-        (cons (list prop value) (js2-node-props node))))
-
-(defsubst js2-fixup-starts (n nodes)
-  "Adjust the start positions of NODES to be relative to N.
-Any node in the list may be nil, for convenience."
-  (dolist (node nodes)
-    (when node
-      (setf (js2-node-pos node) (- (js2-node-pos node)
-                                   (js2-node-pos n))))))
-
-(defsubst js2-node-add-children (parent &rest nodes)
-  "Set parent node of NODES to PARENT, and return PARENT.
-Does nothing if we're not recording parent links.
-If any given node in NODES is nil, doesn't record that link."
-  (js2-fixup-starts parent nodes)
-  (dolist (node nodes)
-    (and node
-         (setf (js2-node-parent node) parent))))
-
-;; Non-recursive since it's called a frightening number of times.
-(defsubst js2-node-abs-pos (n)
-  (let ((pos (js2-node-pos n)))
-    (while (setq n (js2-node-parent n))
-      (setq pos (+ pos (js2-node-pos n))))
-    pos))
-
-(defsubst js2-node-abs-end (n)
-  "Return absolute buffer position of end of N."
-  (+ (js2-node-abs-pos n) (js2-node-len n)))
-
-;; It's important to make sure block nodes have a lisp list for the
-;; child nodes, to limit printing recursion depth in an AST that
-;; otherwise consists of defstruct vectors.  Emacs will crash printing
-;; a sufficiently large vector tree.
-
-(defstruct (js2-block-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-block-node (&key (type js2-BLOCK)
-                                                    (pos js2-token-beg)
-                                                    len
-                                                    props
-                                                    kids)))
-  "A block of statements."
-  kids)  ; a lisp list of the child statement nodes
-
-(put 'cl-struct-js2-block-node 'js2-visitor 'js2-visit-block)
-(put 'cl-struct-js2-block-node 'js2-printer 'js2-print-block)
-
-(defsubst js2-visit-block (ast callback)
-  "Visit the `js2-block-node' children of AST."
-  (dolist (kid (js2-block-node-kids ast))
-    (js2-visit-ast kid callback)))
-
-(defun js2-print-block (n i)
-  (let ((pad (js2-make-pad i)))
-    (insert pad "{\n")
-    (dolist (kid (js2-block-node-kids n))
-      (js2-print-ast kid (1+ i)))
-    (insert pad "}")))
-
-(defstruct (js2-scope
-            (:include js2-block-node)
-            (:constructor nil)
-            (:constructor make-js2-scope (&key (type js2-BLOCK)
-                                               (pos js2-token-beg)
-                                               len
-                                               kids)))
-  ;; The symbol-table is a LinkedHashMap<String,Symbol> in Rhino.
-  ;; I don't have one of those handy, so I'll use an alist for now.
-  ;; It's as fast as an emacs hashtable for up to about 50 elements,
-  ;; and is much lighter-weight to construct (both CPU and mem).
-  ;; The keys are interned strings (symbols) for faster lookup.
-  ;; Should switch to hybrid alist/hashtable eventually.
-  symbol-table  ; an alist of (symbol . js2-symbol)
-  parent-scope  ; a `js2-scope'
-  top)          ; top-level `js2-scope' (script/function)
-
-(put 'cl-struct-js2-scope 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-scope 'js2-printer 'js2-print-none)
-
-(defun js2-scope-set-parent-scope (scope parent)
-  (setf (js2-scope-parent-scope scope) parent
-        (js2-scope-top scope) (if (null parent)
-                                  scope
-                                (js2-scope-top parent))))
-
-(defun js2-node-get-enclosing-scope (node)
-  "Return the innermost `js2-scope' node surrounding NODE.
-Returns nil if there is no enclosing scope node."
-  (let ((parent (js2-node-parent node)))
-    (while (not (js2-scope-p parent))
-      (setq parent (js2-node-parent parent)))
-    parent))
-
-(defun js2-get-defining-scope (scope name)
-  "Search up scope chain from SCOPE looking for NAME, a string or symbol.
-Returns `js2-scope' in which NAME is defined, or nil if not found."
-  (let ((sym (if (symbolp name)
-                 name
-               (intern name)))
-        table
-        result
-        (continue t))
-    (while (and scope continue)
-      (if (and (setq table (js2-scope-symbol-table scope))
-               (assq sym table))
-          (setq continue nil
-                result scope)
-        (setq scope (js2-scope-parent-scope scope))))
-    result))
-
-(defsubst js2-scope-get-symbol (scope name)
-  "Return symbol table entry for NAME in SCOPE.
-NAME can be a string or symbol.   Returns a `js2-symbol' or nil if not found."
-  (and (js2-scope-symbol-table scope)
-       (cdr (assq (if (symbolp name)
-                      name
-                    (intern name))
-                  (js2-scope-symbol-table scope)))))
-
-(defsubst js2-scope-put-symbol (scope name symbol)
-  "Enter SYMBOL into symbol-table for SCOPE under NAME.
-NAME can be a lisp symbol or string.  SYMBOL is a `js2-symbol'."
-  (let* ((table (js2-scope-symbol-table scope))
-         (sym (if (symbolp name) name (intern name)))
-         (entry (assq sym table)))
-    (if entry
-        (setcdr entry symbol)
-      (push (cons sym symbol)
-            (js2-scope-symbol-table scope)))))
-
-(defstruct (js2-symbol
-            (:constructor nil)
-            (:constructor make-js2-symbol (decl-type name &optional ast-node)))
-  "A symbol table entry."
-  ;; One of js2-FUNCTION, js2-LP (for parameters), js2-VAR,
-  ;; js2-LET, or js2-CONST
-  decl-type
-  name  ; string
-  ast-node) ; a `js2-node'
-
-(defstruct (js2-error-node
-            (:include js2-node)
-            (:constructor nil) ; silence emacs21 byte-compiler
-            (:constructor make-js2-error-node (&key (type js2-ERROR)
-                                                    (pos js2-token-beg)
-                                                    len)))
-  "AST node representing a parse error.")
-
-(put 'cl-struct-js2-error-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-error-node 'js2-printer 'js2-print-none)
-
-(defstruct (js2-script-node
-            (:include js2-scope)
-            (:constructor nil)
-            (:constructor make-js2-script-node (&key (type js2-SCRIPT)
-                                                     (pos js2-token-beg)
-                                                     len
-                                                     var-decls
-                                                     fun-decls)))
-  functions   ; lisp list of nested functions
-  regexps     ; lisp list of (string . flags)
-  symbols     ; alist (every symbol gets unique index)
-  (param-count 0)
-  var-names   ; vector of string names
-  consts      ; bool-vector matching var-decls
-  (temp-number 0))  ; for generating temp variables
-
-(put 'cl-struct-js2-script-node 'js2-visitor 'js2-visit-block)
-(put 'cl-struct-js2-script-node 'js2-printer 'js2-print-script)
-
-(defun js2-print-script (node indent)
-  (dolist (kid (js2-block-node-kids node))
-    (js2-print-ast kid indent)))
-
-(defstruct (js2-ast-root
-            (:include js2-script-node)
-            (:constructor nil)
-            (:constructor make-js2-ast-root (&key (type js2-SCRIPT)
-                                                  (pos js2-token-beg)
-                                                  len
-                                                  buffer)))
-  "The root node of a js2 AST."
-  buffer         ; the source buffer from which the code was parsed
-  comments       ; a lisp list of comments, ordered by start position
-  errors         ; a lisp list of errors found during parsing
-  warnings       ; a lisp list of warnings found during parsing
-  node-count)    ; number of nodes in the tree, including the root
-
-(put 'cl-struct-js2-ast-root 'js2-visitor 'js2-visit-ast-root)
-(put 'cl-struct-js2-ast-root 'js2-printer 'js2-print-script)
-
-(defun js2-visit-ast-root (ast callback)
-  (dolist (kid (js2-ast-root-kids ast))
-    (js2-visit-ast kid callback))
-  (dolist (comment (js2-ast-root-comments ast))
-    (js2-visit-ast comment callback)))
-
-(defstruct (js2-comment-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-comment-node (&key (type js2-COMMENT)
-                                                      (pos js2-token-beg)
-                                                      len
-                                                      (format js2-ts-comment-type))))
-  format)  ; 'line, 'block, 'jsdoc or 'html
-
-(put 'cl-struct-js2-comment-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-comment-node 'js2-printer 'js2-print-comment)
-
-(defun js2-print-comment (n i)
-  ;; We really ought to link end-of-line comments to their nodes.
-  ;; Or maybe we could add a new comment type, 'endline.
-  (insert (js2-make-pad i)
-          (js2-node-string n)))
-
-(defstruct (js2-expr-stmt-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-expr-stmt-node (&key (type js2-EXPR_VOID)
-                                                        (pos js2-ts-cursor)
-                                                        len
-                                                        expr)))
-  "An expression statement."
-  expr)
-
-(defsubst js2-expr-stmt-node-set-has-result (node)
-  "Change the node type to `js2-EXPR_RESULT'.  Used for code generation."
-  (setf (js2-node-type node) js2-EXPR_RESULT))
-
-(put 'cl-struct-js2-expr-stmt-node 'js2-visitor 'js2-visit-expr-stmt-node)
-(put 'cl-struct-js2-expr-stmt-node 'js2-printer 'js2-print-expr-stmt-node)
-
-(defun js2-visit-expr-stmt-node (n v)
-  (js2-visit-ast (js2-expr-stmt-node-expr n) v))
-
-(defun js2-print-expr-stmt-node (n indent)
-  (js2-print-ast (js2-expr-stmt-node-expr n) indent)
-  (insert ";\n"))
-
-(defstruct (js2-loop-node
-            (:include js2-scope)
-            (:constructor nil))
-  "Abstract supertype of loop nodes."
-  body      ; a `js2-block-node'
-  lp        ; position of left-paren, nil if omitted
-  rp)       ; position of right-paren, nil if omitted
-
-(defstruct (js2-do-node
-            (:include js2-loop-node)
-            (:constructor nil)
-            (:constructor make-js2-do-node (&key (type js2-DO)
-                                                 (pos js2-token-beg)
-                                                 len
-                                                 body
-                                                 condition
-                                                 while-pos
-                                                 lp
-                                                 rp)))
-  "AST node for do-loop."
-  condition  ; while (expression)
-  while-pos) ; buffer position of 'while' keyword
-
-(put 'cl-struct-js2-do-node 'js2-visitor 'js2-visit-do-node)
-(put 'cl-struct-js2-do-node 'js2-printer 'js2-print-do-node)
-
-(defun js2-visit-do-node (n v)
-  (js2-visit-ast (js2-do-node-body n) v)
-  (js2-visit-ast (js2-do-node-condition n) v))
-
-(defun js2-print-do-node (n i)
-  (let ((pad (js2-make-pad i)))
-    (insert pad "do {\n")
-    (dolist (kid (js2-block-node-kids (js2-do-node-body n)))
-      (js2-print-ast kid (1+ i)))
-    (insert pad "} while (")
-    (js2-print-ast (js2-do-node-condition n) 0)
-    (insert ");\n")))
-
-(defstruct (js2-while-node
-            (:include js2-loop-node)
-            (:constructor nil)
-            (:constructor make-js2-while-node (&key (type js2-WHILE)
-                                                    (pos js2-token-beg)
-                                                    len
-                                                    body
-                                                    condition
-                                                    lp
-                                                    rp)))
-  "AST node for while-loop."
-  condition)    ; while-condition
-
-(put 'cl-struct-js2-while-node 'js2-visitor 'js2-visit-while-node)
-(put 'cl-struct-js2-while-node 'js2-printer 'js2-print-while-node)
-
-(defun js2-visit-while-node (n v)
-  (js2-visit-ast (js2-while-node-condition n) v)
-  (js2-visit-ast (js2-while-node-body n) v))
-
-(defun js2-print-while-node (n i)
-  (let ((pad (js2-make-pad i)))
-    (insert pad "while (")
-    (js2-print-ast (js2-while-node-condition n) 0)
-    (insert ") {\n")
-    (js2-print-body (js2-while-node-body n) (1+ i))
-    (insert pad "}\n")))
-
-(defstruct (js2-for-node
-            (:include js2-loop-node)
-            (:constructor nil)
-            (:constructor make-js2-for-node (&key (type js2-FOR)
-                                                  (pos js2-ts-cursor)
-                                                  len
-                                                  body
-                                                  init
-                                                  condition
-                                                  update
-                                                  lp
-                                                  rp)))
-  "AST node for a C-style for-loop."
-  init       ; initialization expression
-  condition  ; loop condition
-  update)    ; update clause
-
-(put 'cl-struct-js2-for-node 'js2-visitor 'js2-visit-for-node)
-(put 'cl-struct-js2-for-node 'js2-printer 'js2-print-for-node)
-
-(defun js2-visit-for-node (n v)
-  (js2-visit-ast (js2-for-node-init n) v)
-  (js2-visit-ast (js2-for-node-condition n) v)
-  (js2-visit-ast (js2-for-node-update n) v)
-  (js2-visit-ast (js2-for-node-body n) v))
-
-(defun js2-print-for-node (n i)
-  (let ((pad (js2-make-pad i)))
-    (insert pad "for (")
-    (js2-print-ast (js2-for-node-init n) 0)
-    (insert "; ")
-    (js2-print-ast (js2-for-node-condition n) 0)
-    (insert "; ")
-    (js2-print-ast (js2-for-node-update n) 0)
-    (insert ") {\n")
-    (js2-print-body (js2-for-node-body n) (1+ i))
-    (insert pad "}\n")))
-
-(defstruct (js2-for-in-node
-            (:include js2-loop-node)
-            (:constructor nil)
-            (:constructor make-js2-for-in-node (&key (type js2-FOR)
-                                                     (pos js2-ts-cursor)
-                                                     len
-                                                     body
-                                                     iterator
-                                                     object
-                                                     in-pos
-                                                     each-pos
-                                                     foreach-p
-                                                     lp
-                                                     rp)))
-  "AST node for a for..in loop."
-  iterator  ; [var] foo in ...
-  object    ; object over which we're iterating
-  in-pos    ; buffer position of 'in' keyword
-  each-pos  ; buffer position of 'each' keyword, if foreach-p
-  foreach-p) ; t if it's a for-each loop
-
-(put 'cl-struct-js2-for-in-node 'js2-visitor 'js2-visit-for-in-node)
-(put 'cl-struct-js2-for-in-node 'js2-printer 'js2-print-for-in-node)
-
-(defun js2-visit-for-in-node (n v)
-  (js2-visit-ast (js2-for-in-node-iterator n) v)
-  (js2-visit-ast (js2-for-in-node-object n) v)
-  (js2-visit-ast (js2-for-in-node-body n) v))
-
-(defun js2-print-for-in-node (n i)
-  (let ((pad (js2-make-pad i))
-        (foreach (js2-for-in-node-foreach-p n)))
-    (insert pad "for ")
-    (if foreach
-        (insert "each "))
-    (insert "(")
-    (js2-print-ast (js2-for-in-node-iterator n) 0)
-    (insert " in ")
-    (js2-print-ast (js2-for-in-node-object n) 0)
-    (insert ") {\n")
-    (js2-print-body (js2-for-in-node-body n) (1+ i))
-    (insert pad "}\n")))
-
-(defstruct (js2-return-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-return-node (&key (type js2-RETURN)
-                                                     (pos js2-ts-cursor)
-                                                     len
-                                                     retval)))
-  "AST node for a return statement."
-  retval)  ; expression to return, or 'undefined
-
-(put 'cl-struct-js2-return-node 'js2-visitor 'js2-visit-return-node)
-(put 'cl-struct-js2-return-node 'js2-printer 'js2-print-return-node)
-
-(defun js2-visit-return-node (n v)
-  (if (js2-return-node-retval n)
-      (js2-visit-ast (js2-return-node-retval n) v)))
-
-(defun js2-print-return-node (n i)
-  (insert (js2-make-pad i) "return")
-  (when (js2-return-node-retval n)
-    (insert " ")
-    (js2-print-ast (js2-return-node-retval n) 0))
-  (insert ";\n"))
-
-(defstruct (js2-if-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-if-node (&key (type js2-IF)
-                                                 (pos js2-ts-cursor)
-                                                 len
-                                                 condition
-                                                 then-part
-                                                 else-pos
-                                                 else-part
-                                                 lp
-                                                 rp)))
-  "AST node for an if-statement."
-  condition   ; expression
-  then-part   ; statement or block
-  else-pos    ; optional buffer position of 'else' keyword
-  else-part   ; optional statement or block
-  lp          ; position of left-paren, nil if omitted
-  rp)         ; position of right-paren, nil if omitted
-
-(put 'cl-struct-js2-if-node 'js2-visitor 'js2-visit-if-node)
-(put 'cl-struct-js2-if-node 'js2-printer 'js2-print-if-node)
-
-(defun js2-visit-if-node (n v)
-  (js2-visit-ast (js2-if-node-condition n) v)
-  (js2-visit-ast (js2-if-node-then-part n) v)
-  (if (js2-if-node-else-part n)
-      (js2-visit-ast (js2-if-node-else-part n) v)))
-
-(defun js2-print-if-node (n i)
-  (let ((pad (js2-make-pad i))
-        (then-part (js2-if-node-then-part n))
-        (else-part (js2-if-node-else-part n)))
-    (insert pad "if (")
-    (js2-print-ast (js2-if-node-condition n) 0)
-    (insert ") {\n")
-    (js2-print-body then-part (1+ i))
-    (insert pad "}")
-    (cond
-     ((not else-part)
-      (insert "\n"))
-     ((js2-if-node-p else-part)
-      (insert " else ")
-      (js2-print-body else-part i))
-     (t
-      (insert " else {\n")
-      (js2-print-body else-part (1+ i))
-      (insert pad "}\n")))))
-
-(defstruct (js2-try-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-try-node (&key (type js2-TRY)
-                                                  (pos js2-ts-cursor)
-                                                  len
-                                                  try-block
-                                                  catch-clauses
-                                                  finally-block)))
-  "AST node for a try-statement."
-  try-block
-  catch-clauses  ; a lisp list of `js2-catch-node'
-  finally-block) ; a `js2-finally-node'
-
-(put 'cl-struct-js2-try-node 'js2-visitor 'js2-visit-try-node)
-(put 'cl-struct-js2-try-node 'js2-printer 'js2-print-try-node)
-
-(defun js2-visit-try-node (n v)
-  (js2-visit-ast (js2-try-node-try-block n) v)
-  (dolist (clause (js2-try-node-catch-clauses n))
-    (js2-visit-ast clause v))
-  (if (js2-try-node-finally-block n)
-      (js2-visit-ast (js2-try-node-finally-block n) v)))
-
-(defun js2-print-try-node (n i)
-  (let ((pad (js2-make-pad i))
-        (catches (js2-try-node-catch-clauses n))
-        (finally (js2-try-node-finally-block n)))
-    (insert pad "try {\n")
-    (js2-print-body (js2-try-node-try-block n) (1+ i))
-    (insert pad "}")
-    (when catches
-      (dolist (catch catches)
-        (js2-print-ast catch i)))
-    (if finally
-        (js2-print-ast finally i)
-      (insert "\n"))))
-
-(defstruct (js2-catch-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-catch-node (&key (type js2-CATCH)
-                                                    (pos js2-ts-cursor)
-                                                    len
-                                                    var-name
-                                                    guard-kwd
-                                                    guard-expr
-                                                    block
-                                                    lp
-                                                    rp)))
-  "AST node for a catch clause."
-  var-name    ; a `js2-name-node'
-  guard-kwd   ; relative buffer position of "if" in "catch (x if ...)"
-  guard-expr  ; catch condition, a `js2-node'
-  block       ; statements, a `js2-block-node'
-  lp          ; buffer position of left-paren, nil if omitted
-  rp)         ; buffer position of right-paren, nil if omitted
-
-(put 'cl-struct-js2-catch-node 'js2-visitor 'js2-visit-catch-node)
-(put 'cl-struct-js2-catch-node 'js2-printer 'js2-print-catch-node)
-
-(defun js2-visit-catch-node (n v)
-  (js2-visit-ast (js2-catch-node-var-name n) v)
-  (when (js2-catch-node-guard-kwd n)
-    (js2-visit-ast (js2-catch-node-guard-expr n) v))
-  (js2-visit-ast (js2-catch-node-block n) v))
-
-(defun js2-print-catch-node (n i)
-  (let ((pad (js2-make-pad i))
-        (guard-kwd (js2-catch-node-guard-kwd n))
-        (guard-expr (js2-catch-node-guard-expr n)))
-    (insert " catch (")
-    (js2-print-ast (js2-catch-node-var-name n) 0)
-    (when guard-kwd
-      (insert " if ")
-      (js2-print-ast guard-expr 0))
-    (insert ") {\n")
-    (js2-print-body (js2-catch-node-block n) (1+ i))
-    (insert pad "}")))
-
-(defstruct (js2-finally-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-finally-node (&key (type js2-FINALLY)
-                                                      (pos js2-ts-cursor)
-                                                      len
-                                                      body)))
-  "AST node for a finally clause."
-  body)  ; a `js2-node', often but not always a block node
-
-(put 'cl-struct-js2-finally-node 'js2-visitor 'js2-visit-finally-node)
-(put 'cl-struct-js2-finally-node 'js2-printer 'js2-print-finally-node)
-
-(defun js2-visit-finally-node (n v)
-  (js2-visit-ast (js2-finally-node-body n) v))
-
-(defun js2-print-finally-node (n i)
-  (let ((pad (js2-make-pad i)))
-    (insert " finally {\n")
-    (js2-print-body (js2-finally-node-body n) (1+ i))
-    (insert pad "}\n")))
-
-(defstruct (js2-switch-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-switch-node (&key (type js2-SWITCH)
-                                                     (pos js2-ts-cursor)
-                                                     len
-                                                     discriminant
-                                                     cases
-                                                     lp
-                                                     rp)))
-  "AST node for a switch statement."
-  discriminant  ; a `js2-node' (switch expression)
-  cases  ; a lisp list of `js2-case-node'
-  lp     ; position of open-paren for discriminant, nil if omitted
-  rp)    ; position of close-paren for discriminant, nil if omitted
-
-(put 'cl-struct-js2-switch-node 'js2-visitor 'js2-visit-switch-node)
-(put 'cl-struct-js2-switch-node 'js2-printer 'js2-print-switch-node)
-
-(defun js2-visit-switch-node (n v)
-  (js2-visit-ast (js2-switch-node-discriminant n) v)
-  (dolist (c (js2-switch-node-cases n))
-    (js2-visit-ast c v)))
-
-(defun js2-print-switch-node (n i)
-  (let ((pad (js2-make-pad i))
-        (cases (js2-switch-node-cases n)))
-    (insert pad "switch (")
-    (js2-print-ast (js2-switch-node-discriminant n) 0)
-    (insert ") {\n")
-    (dolist (case cases)
-      (js2-print-ast case i))
-    (insert pad "}\n")))
-
-(defstruct (js2-case-node
-            (:include js2-block-node)
-            (:constructor nil)
-            (:constructor make-js2-case-node (&key (type js2-CASE)
-                                                   (pos js2-ts-cursor)
-                                                   len
-                                                   kids
-                                                   expr)))
-  "AST node for a case clause of a switch statement."
-  expr)   ; the case expression (nil for default)
-
-(put 'cl-struct-js2-case-node 'js2-visitor 'js2-visit-case-node)
-(put 'cl-struct-js2-case-node 'js2-printer 'js2-print-case-node)
-
-(defun js2-visit-case-node (n v)
-  (if (js2-case-node-expr n)  ; nil for default: case
-      (js2-visit-ast (js2-case-node-expr n) v))
-  (js2-visit-block n v))
-
-(defun js2-print-case-node (n i)
-  (let ((pad (js2-make-pad i))
-        (expr (js2-case-node-expr n)))
-    (insert pad)
-    (if (null expr)
-        (insert "default:\n")
-      (insert "case ")
-      (js2-print-ast expr 0)
-      (insert ":\n"))
-    (dolist (kid (js2-case-node-kids n))
-      (js2-print-ast kid (1+ i)))))
-
-(defstruct (js2-throw-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-throw-node (&key (type js2-THROW)
-                                                    (pos js2-ts-cursor)
-                                                    len
-                                                    expr)))
-  "AST node for a throw statement."
-  expr)   ; the expression to throw
-
-(put 'cl-struct-js2-throw-node 'js2-visitor 'js2-visit-throw-node)
-(put 'cl-struct-js2-throw-node 'js2-printer 'js2-print-throw-node)
-
-(defun js2-visit-throw-node (n v)
-  (js2-visit-ast (js2-throw-node-expr n) v))
-
-(defun js2-print-throw-node (n i)
-  (insert (js2-make-pad i) "throw ")
-  (js2-print-ast (js2-throw-node-expr n) 0)
-  (insert ";\n"))
-
-(defstruct (js2-with-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-with-node (&key (type js2-WITH)
-                                                   (pos js2-ts-cursor)
-                                                   len
-                                                   object
-                                                   body
-                                                   lp
-                                                   rp)))
-  "AST node for a with-statement."
-  object
-  body
-  lp    ; buffer position of left-paren around object, nil if omitted
-  rp)   ; buffer position of right-paren around object, nil if omitted
-
-(put 'cl-struct-js2-with-node 'js2-visitor 'js2-visit-with-node)
-(put 'cl-struct-js2-with-node 'js2-printer 'js2-print-with-node)
-
-(defun js2-visit-with-node (n v)
-  (js2-visit-ast (js2-with-node-object n) v)
-  (js2-visit-ast (js2-with-node-body n) v))
-
-(defun js2-print-with-node (n i)
-  (let ((pad (js2-make-pad i)))
-    (insert pad "with (")
-    (js2-print-ast (js2-with-node-object n) 0)
-    (insert ") {\n")
-    (js2-print-body (js2-with-node-body n) (1+ i))
-    (insert pad "}\n")))
-
-(defstruct (js2-label-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-label-node (&key (type js2-LABEL)
-                                                    (pos js2-ts-cursor)
-                                                    len
-                                                    name)))
-  "AST node for a statement label or case label."
-  name   ; a string
-  loop)  ; for validating and code-generating continue-to-label
-
-(put 'cl-struct-js2-label-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-label-node 'js2-printer 'js2-print-label)
-
-(defun js2-print-label (n i)
-  (insert (js2-make-pad i)
-          (js2-label-node-name n)
-          ":\n"))
-
-(defstruct (js2-labeled-stmt-node
-            (:include js2-node)
-            (:constructor nil)
-            ;; type needs to be in `js2-side-effecting-tokens' to avoid spurious
-            ;; no-side-effects warnings, hence js2-EXPR_RESULT.
-            (:constructor make-js2-labeled-stmt-node (&key (type js2-EXPR_RESULT)
-                                                           (pos js2-ts-cursor)
-                                                           len
-                                                           labels
-                                                           stmt)))
-  "AST node for a statement with one or more labels.
-Multiple labels for a statement are collapsed into the labels field."
-  labels  ; lisp list of `js2-label-node'
-  stmt)   ; the statement these labels are for
-
-(put 'cl-struct-js2-labeled-stmt-node 'js2-visitor 'js2-visit-labeled-stmt)
-(put 'cl-struct-js2-labeled-stmt-node 'js2-printer 'js2-print-labeled-stmt)
-
-(defun js2-get-label-by-name (lbl-stmt name)
-  "Return a `js2-label-node' by NAME from LBL-STMT's labels list.
-Returns nil if no such label is in the list."
-  (let ((label-list (js2-labeled-stmt-node-labels lbl-stmt))
-        result)
-    (while (and label-list (not result))
-      (if (string= (js2-label-node-name (car label-list)) name)
-          (setq result (car label-list))
-        (setq label-list (cdr label-list))))
-    result))
-
-(defun js2-visit-labeled-stmt (n v)
-  (dolist (label (js2-labeled-stmt-node-labels n))
-    (js2-visit-ast label v))
-  (js2-visit-ast (js2-labeled-stmt-node-stmt n) v))
-
-(defun js2-print-labeled-stmt (n i)
-  (dolist (label (js2-labeled-stmt-node-labels n))
-    (js2-print-ast label i))
-  (js2-print-ast (js2-labeled-stmt-node-stmt n) (1+ i)))
-
-(defun js2-labeled-stmt-node-contains (node label)
-  "Return t if NODE contains LABEL in its label set.
-NODE is a `js2-labels-node'.  LABEL is an identifier."
-  (loop for nl in (js2-labeled-stmt-node-labels node)
-        if (string= label (js2-label-node-name nl))
-          return t
-        finally return nil))
-
-(defsubst js2-labeled-stmt-node-add-label (node label)
-  "Add a `js2-label-node' to the label set for this statement."
-  (setf (js2-labeled-stmt-node-labels node)
-        (nconc (js2-labeled-stmt-node-labels node) (list label))))
-
-(defstruct (js2-jump-node
-            (:include js2-node)
-            (:constructor nil))
-  "Abstract supertype of break and continue nodes."
-  label   ; `js2-name-node' for location of label identifier, if present
-  target) ; target js2-labels-node or loop/switch statement
-
-(defun js2-visit-jump-node (n v)
-  ;; we don't visit the target, since it's a back-link
-  (if (js2-jump-node-label n)
-      (js2-visit-ast (js2-jump-node-label n) v)))
-
-(defstruct (js2-break-node
-            (:include js2-jump-node)
-            (:constructor nil)
-            (:constructor make-js2-break-node (&key (type js2-BREAK)
-                                                    (pos js2-ts-cursor)
-                                                    len
-                                                    label
-                                                    target)))
-  "AST node for a break statement.
-The label field is a `js2-name-node', possibly nil, for the named label
-if provided.  E.g. in 'break foo', it represents 'foo'.  The target field
-is the target of the break - a label node or enclosing loop/switch statement.")
-
-(put 'cl-struct-js2-break-node 'js2-visitor 'js2-visit-jump-node)
-(put 'cl-struct-js2-break-node 'js2-printer 'js2-print-break-node)
-
-(defun js2-print-break-node (n i)
-  (insert (js2-make-pad i) "break")
-  (when (js2-break-node-label n)
-    (insert " ")
-    (js2-print-ast (js2-break-node-label n) 0))
-  (insert ";\n"))
-
-(defstruct (js2-continue-node
-            (:include js2-jump-node)
-            (:constructor nil)
-            (:constructor make-js2-continue-node (&key (type js2-CONTINUE)
-                                                       (pos js2-ts-cursor)
-                                                       len
-                                                       label
-                                                       target)))
-  "AST node for a continue statement.
-The label field is the user-supplied enclosing label name, a `js2-name-node'.
-It is nil if continue specifies no label.  The target field is the jump target:
-a `js2-label-node' or the innermost enclosing loop.")
-
-(put 'cl-struct-js2-continue-node 'js2-visitor 'js2-visit-jump-node)
-(put 'cl-struct-js2-continue-node 'js2-printer 'js2-print-continue-node)
-
-(defun js2-print-continue-node (n i)
-  (insert (js2-make-pad i) "continue")
-  (when (js2-continue-node-label n)
-    (insert " ")
-    (js2-print-ast (js2-continue-node-label n) 0))
-  (insert ";\n"))
-
-(defstruct (js2-function-node
-            (:include js2-script-node)
-            (:constructor nil)
-            (:constructor make-js2-function-node (&key (type js2-FUNCTION)
-                                                       (pos js2-ts-cursor)
-                                                       len
-                                                       (ftype 'FUNCTION)
-                                                       (form 'FUNCTION_STATEMENT)
-                                                       (name "")
-                                                       params
-                                                       body
-                                                       lp
-                                                       rp)))
-  "AST node for a function declaration.
-The `params' field is a lisp list of nodes.  Each node is either a simple
-`js2-name-node', or if it's a destructuring-assignment parameter, a
-`js2-array-node' or `js2-object-node'."
-  ftype            ; FUNCTION, GETTER or SETTER
-  form             ; FUNCTION_{STATEMENT|EXPRESSION|EXPRESSION_STATEMENT}
-  name             ; function name (a `js2-name-node', or nil if anonymous)
-  params           ; a lisp list of destructuring forms or simple name nodes
-  body             ; a `js2-block-node'
-  lp               ; position of arg-list open-paren, or nil if omitted
-  rp               ; position of arg-list close-paren, or nil if omitted
-  ignore-dynamic   ; ignore value of the dynamic-scope flag (interpreter only)
-  needs-activation ; t if we need an activation object for this frame
-  is-generator     ; t if this function contains a yield
-  member-expr)     ; nonstandard Ecma extension from Rhino
-
-(put 'cl-struct-js2-function-node 'js2-visitor 'js2-visit-function-node)
-(put 'cl-struct-js2-function-node 'js2-printer 'js2-print-function-node)
-
-(defun js2-visit-function-node (n v)
-  (if (js2-function-node-name n)
-      (js2-visit-ast (js2-function-node-name n) v))
-  (dolist (p (js2-function-node-params n))
-    (js2-visit-ast p v))
-  (js2-visit-ast (js2-function-node-body n) v))
-
-(defun js2-print-function-node (n i)
-  (let ((pad (js2-make-pad i))
-        (getter (js2-node-get-prop n 'GETTER_SETTER))
-        (name (js2-function-node-name n))
-        (params (js2-function-node-params n))
-        (body (js2-function-node-body n))
-        (expr (eq (js2-function-node-form n) 'FUNCTION_EXPRESSION)))
-    (unless getter
-      (insert pad "function"))
-    (when name
-        (insert " ")
-        (js2-print-ast name 0))
-    (insert "(")
-    (loop with len = (length params)
-          for param in params
-          for count from 1
-          do
-          (js2-print-ast param 0)
-          (if (< count len)
-              (insert ", ")))
-    (insert ") {")
-    (unless expr
-      (insert "\n"))
-    ;; TODO:  fix this to be smarter about indenting, etc.
-    (js2-print-body body (1+ i))
-    (insert pad "}")
-    (unless expr
-      (insert "\n"))))
-
-(defsubst js2-function-name (node)
-  "Return function name for NODE, a `js2-function-node', or nil if anonymous."
-  (and (js2-function-node-name node)
-       (js2-name-node-name (js2-function-node-name node))))
-
-;; Having this be an expression node makes it more flexible.
-;; There are IDE contexts, such as indentation in a for-loop initializer,
-;; that work better if you assume it's an expression.  Whenever we have
-;; a standalone var/const declaration, we just wrap with an expr stmt.
-;; Eclipse apparently screwed this up and now has two versions, expr and stmt.
-(defstruct (js2-var-decl-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-var-decl-node (&key (type js2-VAR)
-                                                       (pos js2-token-beg)
-                                                       len
-                                                       kids
-                                                       decl-type)))
-  "AST node for a variable declaration list (VAR, CONST or LET).
-The node bounds differ depending on the declaration type.  For VAR or
-CONST declarations, the bounds include the var/const keyword.  For LET
-declarations, the node begins at the position of the first child."
-  kids        ; a lisp list of `js2-var-init-node' structs.
-  decl-type)  ; js2-VAR, js2-CONST or js2-LET
-
-(put 'cl-struct-js2-var-decl-node 'js2-visitor 'js2-visit-var-decl)
-(put 'cl-struct-js2-var-decl-node 'js2-printer 'js2-print-var-decl)
-
-(defun js2-visit-var-decl (n v)
-  (dolist (kid (js2-var-decl-node-kids n))
-    (js2-visit-ast kid v)))
-
-(defun js2-print-var-decl (n i)
-  (let ((pad (js2-make-pad i))
-        (tt (js2-var-decl-node-decl-type n)))
-    (insert pad)
-    (insert (cond
-             ((= tt js2-VAR) "var ")
-             ((= tt js2-LET) "")  ; handled by parent let-{expr/stmt}
-             ((= tt js2-CONST) "const ")
-             (t
-              (error "malformed var-decl node"))))
-    (loop with kids = (js2-var-decl-node-kids n)
-          with len = (length kids)
-          for kid in kids
-          for count from 1
-          do
-          (js2-print-ast kid 0)
-          (if (< count len)
-              (insert ", ")))))
-
-(defstruct (js2-var-init-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-var-init-node (&key (type js2-VAR)
-                                                       (pos js2-ts-cursor)
-                                                       len
-                                                       target
-                                                       initializer)))
-  "AST node for a variable declaration.
-The type field will be js2-CONST for a const decl."
-  target        ; `js2-name-node', `js2-object-node', or `js2-array-node'
-  initializer)  ; initializer expression, a `js2-node'
-
-(put 'cl-struct-js2-var-init-node 'js2-visitor 'js2-visit-var-init-node)
-(put 'cl-struct-js2-var-init-node 'js2-printer 'js2-print-var-init-node)
-
-(defun js2-visit-var-init-node (n v)
-  (js2-visit-ast (js2-var-init-node-target n) v)
-  (if (js2-var-init-node-initializer n)
-      (js2-visit-ast (js2-var-init-node-initializer n) v)))
-
-(defun js2-print-var-init-node (n i)
-  (let ((pad (js2-make-pad i))
-        (name (js2-var-init-node-target n))
-        (init (js2-var-init-node-initializer n)))
-    (insert pad)
-    (js2-print-ast name 0)
-    (when init
-      (insert " = ")
-      (js2-print-ast init 0))))
-
-(defstruct (js2-cond-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-cond-node (&key (type js2-HOOK)
-                                                   (pos js2-ts-cursor)
-                                                   len
-                                                   test-expr
-                                                   true-expr
-                                                   false-expr
-                                                   q-pos
-                                                   c-pos)))
-  "AST node for the ternary operator"
-  test-expr
-  true-expr
-  false-expr
-  q-pos   ; buffer position of ?
-  c-pos)  ; buffer position of :
-
-(put 'cl-struct-js2-cond-node 'js2-visitor 'js2-visit-cond-node)
-(put 'cl-struct-js2-cond-node 'js2-printer 'js2-print-cond-node)
-
-(defun js2-visit-cond-node (n v)
-  (js2-visit-ast (js2-cond-node-test-expr n) v)
-  (js2-visit-ast (js2-cond-node-true-expr n) v)
-  (js2-visit-ast (js2-cond-node-false-expr n) v))
-
-(defun js2-print-cond-node (n i)
-  (let ((pad (js2-make-pad i)))
-    (insert pad)
-    (js2-print-ast (js2-cond-node-test-expr n) 0)
-    (insert " ? ")
-    (js2-print-ast (js2-cond-node-true-expr n) 0)
-    (insert " : ")
-    (js2-print-ast (js2-cond-node-false-expr n) 0)))
-
-(defstruct (js2-infix-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-infix-node (&key type
-                                                    (pos js2-ts-cursor)
-                                                    len
-                                                    op-pos
-                                                    left
-                                                    right)))
-  "Represents infix expressions.
-Includes assignment ops like `|=', and the comma operator.
-The type field inherited from `js2-node' holds the operator."
-  op-pos    ; buffer position where operator begins
-  left      ; any `js2-node'
-  right)    ; any `js2-node'
-
-(put 'cl-struct-js2-infix-node 'js2-visitor 'js2-visit-infix-node)
-(put 'cl-struct-js2-infix-node 'js2-printer 'js2-print-infix-node)
-
-(defun js2-visit-infix-node (n v)
-  (when (js2-infix-node-left n)
-    (js2-visit-ast (js2-infix-node-left n) v))
-  (when (js2-infix-node-right n)
-    (js2-visit-ast (js2-infix-node-right n) v)))
-
-(defconst js2-operator-tokens
-  (let ((table (make-hash-table :test 'eq))
-        (tokens
-         (list (cons js2-IN "in")
-               (cons js2-TYPEOF "typeof")
-               (cons js2-INSTANCEOF "instanceof")
-               (cons js2-DELPROP "delete")
-               (cons js2-COMMA ",")
-               (cons js2-COLON ":")
-               (cons js2-OR "||")
-               (cons js2-AND "&&")
-               (cons js2-INC "++")
-               (cons js2-DEC "--")
-               (cons js2-BITOR "|")
-               (cons js2-BITXOR "^")
-               (cons js2-BITAND "&")
-               (cons js2-EQ "==")
-               (cons js2-NE "!=")
-               (cons js2-LT "<")
-               (cons js2-LE "<=")
-               (cons js2-GT ">")
-               (cons js2-GE ">=")
-               (cons js2-LSH "<<")
-               (cons js2-RSH ">>")
-               (cons js2-URSH ">>>")
-               (cons js2-ADD "+")       ; infix plus
-               (cons js2-SUB "-")       ; infix minus
-               (cons js2-MUL "*")
-               (cons js2-DIV "/")
-               (cons js2-MOD "%")
-               (cons js2-NOT "!")
-               (cons js2-BITNOT "~")
-               (cons js2-POS "+")       ; unary plus
-               (cons js2-NEG "-")       ; unary minus
-               (cons js2-SHEQ "===")    ; shallow equality
-               (cons js2-SHNE "!==")    ; shallow inequality
-               (cons js2-ASSIGN "=")
-               (cons js2-ASSIGN_BITOR "|=")
-               (cons js2-ASSIGN_BITXOR "^=")
-               (cons js2-ASSIGN_BITAND "&=")
-               (cons js2-ASSIGN_LSH "<<=")
-               (cons js2-ASSIGN_RSH ">>=")
-               (cons js2-ASSIGN_URSH ">>>=")
-               (cons js2-ASSIGN_ADD "+=")
-               (cons js2-ASSIGN_SUB "-=")
-               (cons js2-ASSIGN_MUL "*=")
-               (cons js2-ASSIGN_DIV "/=")
-               (cons js2-ASSIGN_MOD "%="))))
-    (loop for (k . v) in tokens do
-          (puthash k v table))
-    table))
-
-(defun js2-print-infix-node (n i)
-  (let* ((tt (js2-node-type n))
-         (op (gethash tt js2-operator-tokens)))
-    (unless op
-      (error "unrecognized infix operator %s" (js2-node-type n)))
-    (insert (js2-make-pad i))
-    (js2-print-ast (js2-infix-node-left n) 0)
-    (unless (= tt js2-COMMA)
-      (insert " "))
-    (insert op)
-    (insert " ")
-    (js2-print-ast (js2-infix-node-right n) 0)))
-
-(defstruct (js2-assign-node
-            (:include js2-infix-node)
-            (:constructor nil)
-            (:constructor make-js2-assign-node (&key type
-                                                     (pos js2-ts-cursor)
-                                                     len
-                                                     op-pos
-                                                     left
-                                                     right)))
-  "Represents any assignment.
-The type field holds the actual assignment operator.")
-
-(put 'cl-struct-js2-assign-node 'js2-visitor 'js2-visit-infix-node)
-(put 'cl-struct-js2-assign-node 'js2-printer 'js2-print-infix-node)
-
-(defstruct (js2-unary-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-unary-node (&key type ; required
-                                                    (pos js2-ts-cursor)
-                                                    len
-                                                    operand)))
-  "AST node type for unary operator nodes.
-The type field can be NOT, BITNOT, POS, NEG, INC, DEC,
-TYPEOF, or DELPROP.  For INC or DEC, a 'postfix node
-property is added if the operator follows the operand."
-  operand)  ; a `js2-node' expression
-
-(put 'cl-struct-js2-unary-node 'js2-visitor 'js2-visit-unary-node)
-(put 'cl-struct-js2-unary-node 'js2-printer 'js2-print-unary-node)
-
-(defun js2-visit-unary-node (n v)
-  (js2-visit-ast (js2-unary-node-operand n) v))
-
-(defun js2-print-unary-node (n i)
-  (let* ((tt (js2-node-type n))
-         (op (gethash tt js2-operator-tokens))
-         (postfix (js2-node-get-prop n 'postfix)))
-    (unless op
-      (error "unrecognized unary operator %s" tt))
-    (insert (js2-make-pad i))
-    (unless postfix
-      (insert op))
-    (if (or (= tt js2-TYPEOF)
-            (= tt js2-DELPROP))
-        (insert " "))
-    (js2-print-ast (js2-unary-node-operand n) 0)
-    (when postfix
-      (insert op))))
-
-(defstruct (js2-let-node
-            (:include js2-scope)
-            (:constructor nil)
-            (:constructor make-js2-let-node (&key (type js2-LETEXPR)
-                                                  (pos js2-token-beg)
-                                                  len
-                                                  vars
-                                                  body
-                                                  lp
-                                                  rp)))
-  "AST node for a let expression or a let statement.
-Note that a let declaration such as let x=6, y=7 is a `js2-var-decl-node'."
-  vars   ; a `js2-var-decl-node'
-  body   ; a `js2-node' representing the expression or body block
-  lp
-  rp)
-
-(put 'cl-struct-js2-let-node 'js2-visitor 'js2-visit-let-node)
-(put 'cl-struct-js2-let-node 'js2-printer 'js2-print-let-node)
-
-(defun js2-visit-let-node (n v)
-  (when (js2-let-node-vars n)
-    (js2-visit-ast (js2-let-node-vars n) v))
-  (when (js2-let-node-body n)
-    (js2-visit-ast (js2-let-node-body n) v)))
-
-(defun js2-print-let-node (n i)
-  (insert (js2-make-pad i) "let (")
-  (js2-print-ast (js2-let-node-vars n) 0)
-  (insert ") ")
-  (js2-print-ast (js2-let-node-body n) i))
-
-(defstruct (js2-keyword-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-keyword-node (&key type
-                                                      (pos js2-token-beg)
-                                                      (len (- js2-ts-cursor pos)))))
-  "AST node representing a literal keyword such as `null'.
-Used for `null', `this', `true', `false' and `debugger'.
-The node type is set to js2-NULL, js2-THIS, etc.")
-
-(put 'cl-struct-js2-keyword-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-keyword-node 'js2-printer 'js2-print-keyword-node)
-
-(defun js2-print-keyword-node (n i)
-  (insert (js2-make-pad i)
-          (let ((tt (js2-node-type n)))
-            (cond
-             ((= tt 'js2-THIS) "this")
-             ((= tt 'js2-NULL) "null")
-             ((= tt 'js2-TRUE) "true")
-             ((= tt 'js2-FALSE) "false")
-             ((= tt 'js2-DEBUGGER) "debugger")
-             (t (error "Invalid keyword literal type: %d" tt))))))
-
-(defsubst js2-this-node-p (node)
-  "Return t if this node is a `js2-literal-node' of type js2-THIS."
-  (eq (js2-node-type node) js2-THIS))
-
-(defstruct (js2-new-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-new-node (&key (type js2-NEW)
-                                                  (pos js2-token-beg)
-                                                  len
-                                                  target
-                                                  args
-                                                  initializer
-                                                  lp
-                                                  rp)))
-  "AST node for new-expression such as new Foo()."
-  target  ; an identifier or reference
-  args    ; a lisp list of argument nodes
-  lp      ; position of left-paren, nil if omitted
-  rp      ; position of right-paren, nil if omitted
-  initializer) ; experimental Rhino syntax:  optional `js2-object-node'
-
-(put 'cl-struct-js2-new-node 'js2-visitor 'js2-visit-new-node)
-(put 'cl-struct-js2-new-node 'js2-printer 'js2-print-new-node)
-
-(defun js2-visit-new-node (n v)
-  (js2-visit-ast (js2-new-node-target n) v)
-  (dolist (arg (js2-new-node-args n))
-    (js2-visit-ast arg v))
-  (when (js2-new-node-initializer n)
-    (js2-visit-ast (js2-new-node-initializer n) v)))
-
-(defun js2-print-new-node (n i)
-  (insert (js2-make-pad i) "new ")
-  (js2-print-ast (js2-new-node-target n))
-  (insert "(")
-  (js2-print-list (js2-new-node-args n))
-  (insert ")")
-  (when (js2-new-node-initializer n)
-    (insert " ")
-    (js2-print-ast (js2-new-node-initializer n))))
-
-(defstruct (js2-name-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-name-node (&key (type js2-NAME)
-                                                   (pos js2-token-beg)
-                                                   (len (- js2-ts-cursor
-                                                           js2-token-beg))
-                                                   (name js2-ts-string))))
-  "AST node for a JavaScript identifier"
-  name   ; a string
-  scope) ; a `js2-scope' (optional, used for codegen)
-
-(put 'cl-struct-js2-name-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-name-node 'js2-printer 'js2-print-name-node)
-
-(defun js2-print-name-node (n i)
-  (insert (js2-make-pad i)
-          (js2-name-node-name n)))
-
-(defsubst js2-name-node-length (node)
-  "Return identifier length of NODE, a `js2-name-node'.
-Returns 0 if NODE is nil or its identifier field is nil."
-  (if node
-      (length (js2-name-node-name node))
-    0))
-
-(defstruct (js2-number-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-number-node (&key (type js2-NUMBER)
-                                                     (pos js2-token-beg)
-                                                     (len (- js2-ts-cursor
-                                                             js2-token-beg))
-                                                     (value js2-ts-string)
-                                                     (num-value js2-ts-number))))
-  "AST node for a number literal."
-  value      ; the original string, e.g. "6.02e23"
-  num-value) ; the parsed number value
-
-(put 'cl-struct-js2-number-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-number-node 'js2-printer 'js2-print-number-node)
-
-(defun js2-print-number-node (n i)
-  (insert (js2-make-pad i)
-          (number-to-string (js2-number-node-value n))))
-
-(defstruct (js2-regexp-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-regexp-node (&key (type js2-REGEXP)
-                                                     (pos js2-token-beg)
-                                                     (len (- js2-ts-cursor
-                                                             js2-token-beg))
-                                                     value
-                                                     flags)))
-  "AST node for a regular expression literal."
-  value  ; the regexp string, without // delimiters
-  flags) ; a string of flags, e.g. `mi'.
-
-(put 'cl-struct-js2-regexp-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-regexp-node 'js2-printer 'js2-print-regexp)
-
-(defun js2-print-regexp (n i)
-  (insert (js2-make-pad i)
-          "/"
-          (js2-regexp-node-value n)
-          "/")
-  (if (js2-regexp-node-flags n)
-      (insert (js2-regexp-node-flags n))))
-
-(defstruct (js2-string-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-string-node (&key (type js2-STRING)
-                                                     (pos js2-token-beg)
-                                                     (len (- js2-ts-cursor
-                                                             js2-token-beg))
-                                                     (value js2-ts-string))))
-  "String literal.
-Escape characters are not evaluated; e.g. \n is 2 chars in value field.
-You can tell the quote type by looking at the first character."
-  value) ; the characters of the string, including the quotes
-
-(put 'cl-struct-js2-string-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-string-node 'js2-printer 'js2-print-string-node)
-
-(defun js2-print-string-node (n i)
-  (insert (js2-make-pad i)
-          (js2-node-string n)))
-
-(defstruct (js2-array-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-array-node (&key (type js2-ARRAYLIT)
-                                                    (pos js2-ts-cursor)
-                                                    len
-                                                    elems)))
-  "AST node for an array literal."
-  elems)  ; list of expressions.  [foo,,bar] yields a nil middle element.
-
-(put 'cl-struct-js2-array-node 'js2-visitor 'js2-visit-array-node)
-(put 'cl-struct-js2-array-node 'js2-printer 'js2-print-array-node)
-
-(defun js2-visit-array-node (n v)
-  (dolist (e (js2-array-node-elems n))
-    (when e  ; can be nil, e.g. [a, ,b]
-      (js2-visit-ast e v))))
-
-(defun js2-print-array-node (n i)
-  (insert (js2-make-pad i) "[")
-  (js2-print-list (js2-array-node-elems n))
-  (insert "]"))
-
-(defstruct (js2-object-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-object-node (&key (type js2-OBJECTLIT)
-                                                     (pos js2-ts-cursor)
-                                                     len
-                                                     elems)))
-  "AST node for an object literal expression."
-  elems)  ; a lisp list of `js2-object-prop-node'
-
-(put 'cl-struct-js2-object-node 'js2-visitor 'js2-visit-object-node)
-(put 'cl-struct-js2-object-node 'js2-printer 'js2-print-object-node)
-
-(defun js2-visit-object-node (n v)
-  (dolist (e (js2-object-node-elems n))
-    (js2-visit-ast e v)))
-
-(defun js2-print-object-node (n i)
-  (insert (js2-make-pad i) "{")
-  (js2-print-list (js2-object-node-elems n))
-  (insert "}"))
-
-(defstruct (js2-object-prop-node
-            (:include js2-infix-node)
-            (:constructor nil)
-            (:constructor make-js2-object-prop-node (&key (type js2-COLON)
-                                                          (pos js2-ts-cursor)
-                                                          len
-                                                          left
-                                                          right
-                                                          op-pos)))
-  "AST node for an object literal prop:value entry.
-The `left' field is the property:  a name node, string node or number node.
-The `right' field is a `js2-node' representing the initializer value.")
-
-(put 'cl-struct-js2-object-prop-node 'js2-visitor 'js2-visit-infix-node)
-(put 'cl-struct-js2-object-prop-node 'js2-printer 'js2-print-object-prop-node)
-
-(defun js2-print-object-prop-node (n i)
-  (insert (js2-make-pad i))
-  (js2-print-ast (js2-object-prop-node-left n) 0)
-  (insert ":")
-  (js2-print-ast (js2-object-prop-node-right n) 0))
-
-(defstruct (js2-getter-setter-node
-            (:include js2-infix-node)
-            (:constructor nil)
-            (:constructor make-js2-getter-setter-node (&key type ; GET or SET
-                                                            (pos js2-ts-cursor)
-                                                            len
-                                                            left
-                                                            right)))
-  "AST node for a getter/setter property in an object literal.
-The `left' field is the `js2-name-node' naming the getter/setter prop.
-The `right' field is always an anonymous `js2-function-node' with a node
-property `GETTER_SETTER' set to js2-GET or js2-SET. ")
-
-(put 'cl-struct-js2-getter-setter-node 'js2-visitor 'js2-visit-infix-node)
-(put 'cl-struct-js2-getter-setter-node 'js2-printer 'js2-print-getter-setter)
-
-(defun js2-print-getter-setter (n i)
-  (let ((pad (js2-make-pad i))
-        (left (js2-getter-setter-node-left n))
-        (right (js2-getter-setter-node-right n)))
-    (insert pad)
-    (insert (if (= (js2-node-type n) js2-GET) "get " "set "))
-    (js2-print-ast left 0)
-    (js2-print-ast right 0)))
-
-(defstruct (js2-prop-get-node
-            (:include js2-infix-node)
-            (:constructor nil)
-            (:constructor make-js2-prop-get-node (&key (type js2-GETPROP)
-                                                       (pos js2-ts-cursor)
-                                                       len
-                                                       left
-                                                       right)))
-  "AST node for a dotted property reference, e.g. foo.bar or foo().bar")
-
-(put 'cl-struct-js2-prop-get-node 'js2-visitor 'js2-visit-prop-get-node)
-(put 'cl-struct-js2-prop-get-node 'js2-printer 'js2-print-prop-get-node)
-
-(defun js2-visit-prop-get-node (n v)
-  (when (js2-prop-get-node-left n)
-    (js2-visit-ast (js2-prop-get-node-left n) v))
-  (when (js2-prop-get-node-right n)
-    (js2-visit-ast (js2-prop-get-node-right n) v)))
-
-(defun js2-print-prop-get-node (n i)
-  (insert (js2-make-pad i))
-  (js2-print-ast (js2-prop-get-node-left n) 0)
-  (insert ".")
-  (js2-print-ast (js2-prop-get-node-right n) 0))
-
-(defstruct (js2-elem-get-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-elem-get-node (&key (type js2-GETELEM)
-                                                       (pos js2-ts-cursor)
-                                                       len
-                                                       target
-                                                       element
-                                                       lb
-                                                       rb)))
-  "AST node for an array index expression such as foo[bar]."
-  target  ; a `js2-node' - the expression preceding the "."
-  element ; a `js2-node' - the expression in brackets
-  lb      ; position of left-bracket, nil if omitted
-  rb)     ; position of right-bracket, nil if omitted
-
-(put 'cl-struct-js2-elem-get-node 'js2-visitor 'js2-visit-elem-get-node)
-(put 'cl-struct-js2-elem-get-node 'js2-printer 'js2-print-elem-get-node)
-
-(defun js2-visit-elem-get-node (n v)
-  (when (js2-elem-get-node-target n)
-    (js2-visit-ast (js2-elem-get-node-target n) v))
-  (when (js2-elem-get-node-element n)
-    (js2-visit-ast (js2-elem-get-node-element n) v)))
-
-(defun js2-print-elem-get-node (n i)
-  (insert (js2-make-pad i))
-  (js2-print-ast (js2-elem-get-node-target n) 0)
-  (insert "[")
-  (js2-print-ast (js2-elem-get-node-element n) 0)
-  (insert "]"))
-
-(defstruct (js2-call-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-call-node (&key (type js2-CALL)
-                                                   (pos js2-ts-cursor)
-                                                   len
-                                                   target
-                                                   args
-                                                   lp
-                                                   rp)))
-  "AST node for a JavaScript function call."
-  target  ; a `js2-node' evaluating to the function to call
-  args  ; a lisp list of `js2-node' arguments
-  lp    ; position of open-paren, or nil if missing
-  rp)   ; position of close-paren, or nil if missing
-
-(put 'cl-struct-js2-call-node 'js2-visitor 'js2-visit-call-node)
-(put 'cl-struct-js2-call-node 'js2-printer 'js2-print-call-node)
-
-(defun js2-visit-call-node (n v)
-  (js2-visit-ast (js2-call-node-target n) v)
-  (dolist (arg (js2-call-node-args n))
-    (js2-visit-ast arg v)))
-
-(defun js2-print-call-node (n i)
-  (insert (js2-make-pad i))
-  (js2-print-ast (js2-call-node-target n) 0)
-  (insert "(")
-  (js2-print-list (js2-call-node-args n))
-  (insert ")"))
-
-(defstruct (js2-yield-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-yield-node (&key (type js2-YIELD)
-                                                    (pos js2-ts-cursor)
-                                                    len
-                                                    value)))
-  "AST node for yield statement or expression."
-  value) ; optional:  value to be yielded
-
-(put 'cl-struct-js2-yield-node 'js2-visitor 'js2-visit-yield-node)
-(put 'cl-struct-js2-yield-node 'js2-printer 'js2-print-yield-node)
-
-(defun js2-visit-yield-node (n v)
-  (js2-visit-ast (js2-yield-node-value n) v))
-
-(defun js2-print-yield-node (n i)
-  (insert (js2-make-pad i))
-  (insert "yield")
-  (when (js2-yield-node-value n)
-    (insert " ")
-    (js2-print-ast (js2-yield-node-value n) 0)))
-
-(defstruct (js2-paren-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-paren-node (&key (type js2-LP)
-                                                    (pos js2-ts-cursor)
-                                                    len
-                                                    expr)))
-  "AST node for a parenthesized expression.
-In particular, used when the parens are syntactically optional,
-as opposed to required parens such as those enclosing an if-conditional."
-  expr)   ; `js2-node'
-
-(put 'cl-struct-js2-paren-node 'js2-visitor 'js2-visit-paren-node)
-(put 'cl-struct-js2-paren-node 'js2-printer 'js2-print-paren-node)
-
-(defun js2-visit-paren-node (n v)
-  (js2-visit-ast (js2-paren-node-expr n) v))
-
-(defun js2-print-paren-node (n i)
-  (insert (js2-make-pad i))
-  (insert "(")
-  (js2-print-ast (js2-paren-node-expr n) 0)
-  (insert ")"))
-
-(defstruct (js2-array-comp-node
-            (:include js2-scope)
-            (:constructor nil)
-            (:constructor make-js2-array-comp-node (&key (type js2-ARRAYCOMP)
-                                                         (pos js2-ts-cursor)
-                                                         len
-                                                         result
-                                                         loops
-                                                         filter
-                                                         if-pos
-                                                         lp
-                                                         rp)))
-  "AST node for an Array comprehension such as [[x,y] for (x in foo) for (y in bar)]."
-  result  ; result expression (just after left-bracket)
-  loops   ; a lisp list of `js2-array-comp-loop-node'
-  filter  ; guard/filter expression
-  if-pos  ; buffer pos of 'if' keyword, if present, else nil
-  lp      ; buffer position of if-guard left-paren, or nil if not present
-  rp)     ; buffer position of if-guard right-paren, or nil if not present
-
-(put 'cl-struct-js2-array-comp-node 'js2-visitor 'js2-visit-array-comp-node)
-(put 'cl-struct-js2-array-comp-node 'js2-printer 'js2-print-array-comp-node)
-
-(defun js2-visit-array-comp-node (n v)
-  (js2-visit-ast (js2-array-comp-node-result n) v)
-  (dolist (l (js2-array-comp-node-loops n))
-    (js2-visit-ast l v))
-  (if (js2-array-comp-node-filter n)
-      (js2-visit-ast (js2-array-comp-node-filter n) v)))
-
-(defun js2-print-array-comp-node (n i)
-  (let ((pad (js2-make-pad i))
-        (result (js2-array-comp-node-result n))
-        (loops (js2-array-comp-node-loops n))
-        (filter (js2-array-comp-node-filter n)))
-    (insert pad "[")
-    (js2-print-ast result 0)
-    (dolist (l loops)
-      (insert " ")
-      (js2-print-ast l 0))
-    (when filter
-      (insert " if (")
-      (js2-print-ast filter 0))
-    (insert ")]")))
-
-(defstruct (js2-array-comp-loop-node
-            (:include js2-for-in-node)
-            (:constructor nil)
-            (:constructor make-js2-array-comp-loop-node (&key (type js2-FOR)
-                                                              (pos js2-ts-cursor)
-                                                              len
-                                                              iterator
-                                                              object
-                                                              in-pos
-                                                              foreach-p
-                                                              each-pos
-                                                              lp
-                                                              rp)))
-  "AST subtree for each 'for (foo in bar)' loop in an array comprehension.")
-
-(put 'cl-struct-js2-array-comp-loop-node 'js2-visitor 'js2-visit-array-comp-loop)
-(put 'cl-struct-js2-array-comp-loop-node 'js2-printer 'js2-print-array-comp-loop)
-
-(defun js2-visit-array-comp-loop (n v)
-  (js2-visit-ast (js2-array-comp-loop-node-iterator n) v)
-  (js2-visit-ast (js2-array-comp-loop-node-object n) v))
-
-(defun js2-print-array-comp-loop (n i)
-  (insert "for (")
-  (js2-print-ast (js2-array-comp-loop-node-iterator n) 0)
-  (insert " in ")
-  (js2-print-ast (js2-array-comp-loop-node-object n) 0)
-  (insert ")"))
-
-(defstruct (js2-empty-expr-node
-            (:include js2-node)
-            (:constructor nil)
-            (:constructor make-js2-empty-expr-node (&key (type js2-EMPTY)
-                                                         (pos js2-token-beg)
-                                                         len)))
-  "AST node for an empty expression.")
-
-(put 'cl-struct-js2-empty-expr-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-empty-expr-node 'js2-printer 'js2-print-none)
-
-(defstruct (js2-xml-node
-            (:include js2-block-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-node (&key (type js2-XML)
-                                                  (pos js2-token-beg)
-                                                  len
-                                                  kids)))
-  "AST node for initial parse of E4X literals.
-The kids field is a list of XML fragments, each a `js2-string-node' or
-a `js2-xml-js-expr-node'.  Equivalent to Rhino's XmlLiteral node.")
-
-(put 'cl-struct-js2-xml-node 'js2-visitor 'js2-visit-block)
-(put 'cl-struct-js2-xml-node 'js2-printer 'js2-print-xml-node)
-
-(defun js2-print-xml-node (n i)
-  (dolist (kid (js2-xml-node-kids n))
-    (js2-print-ast kid i)))
-
-(defstruct (js2-xml-js-expr-node
-            (:include js2-xml-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-js-expr-node (&key (type js2-XML)
-                                                          (pos js2-ts-cursor)
-                                                          len
-                                                          expr)))
-  "AST node for an embedded JavaScript {expression} in an E4X literal.
-The start and end fields correspond to the curly-braces."
-  expr)  ; a `js2-expr-node' of some sort
-
-(put 'cl-struct-js2-xml-js-expr-node 'js2-visitor 'js2-visit-xml-js-expr)
-(put 'cl-struct-js2-xml-js-expr-node 'js2-printer 'js2-print-xml-js-expr)
-
-(defun js2-visit-xml-js-expr (n v)
-  (js2-visit-ast (js2-xml-js-expr-node-expr n) v))
-
-(defun js2-print-xml-js-expr (n i)
-  (insert (js2-make-pad i))
-  (insert "{")
-  (js2-print-ast (js2-xml-js-expr-node-expr n) 0)
-  (insert "}"))
-
-(defstruct (js2-xml-dot-query-node
-            (:include js2-infix-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-dot-query-node (&key (type js2-DOTQUERY)
-                                                            (pos js2-ts-cursor)
-                                                            op-pos
-                                                            len
-                                                            left
-                                                            right
-                                                            rp)))
-  "AST node for an E4X foo.(bar) filter expression.
-Note that the left-paren is automatically the character immediately
-following the dot (.) in the operator.  No whitespace is permitted
-between the dot and the lp by the scanner."
-  rp)
-
-(put 'cl-struct-js2-xml-dot-query-node 'js2-visitor 'js2-visit-infix-node)
-(put 'cl-struct-js2-xml-dot-query-node 'js2-printer 'js2-print-xml-dot-query)
-
-(defun js2-print-xml-dot-query (n i)
-  (insert (js2-make-pad i))
-  (js2-print-ast (js2-xml-dot-query-node-left n) 0)
-  (insert ".(")
-  (js2-print-ast (js2-xml-dot-query-node-right n) 0)
-  (insert ")"))
-
-(defstruct (js2-xml-ref-node
-            (:include js2-node)
-            (:constructor nil))  ; abstract
-  "Base type for E4X XML attribute-access or property-get expressions.
-Such expressions can take a variety of forms.  The general syntax has
-three parts:
-
-  - (optional) an @ (specifying an attribute access)
-  - (optional) a namespace (a `js2-name-node') and double-colon
-  - (required) either a `js2-name-node' or a bracketed [expression]
-
-The property-name expressions (examples:  ns::name, @name) are
-represented as `js2-xml-prop-ref' nodes.  The bracketed-expression
-versions (examples:  ns::[name], @[name]) become `js2-xml-elem-ref' nodes.
-
-This node type (or more specifically, its subclasses) will sometimes
-be the right-hand child of a `js2-prop-get-node' or a
-`js2-infix-node' of type `js2-DOTDOT', the .. xml-descendants operator.
-The `js2-xml-ref-node' may also be a standalone primary expression with
-no explicit target, which is valid in certain expression contexts such as
-
-  company..employee.(@id < 100)
-
-in this case, the @id is a `js2-xml-ref' that is part of an infix '<'
-expression whose parent is a `js2-xml-dot-query-node'."
-  namespace
-  at-pos
-  colon-pos)
-
-(defsubst js2-xml-ref-node-attr-access-p (node)
-  "Return non-nil if this expression began with an @-token."
-  (and (numberp (js2-xml-ref-node-at-pos node))
-       (plusp (js2-xml-ref-node-at-pos node))))
-
-(defstruct (js2-xml-prop-ref-node
-            (:include js2-xml-ref-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-prop-ref-node (&key (type js2-REF_NAME)
-                                                           (pos js2-token-beg)
-                                                           len
-                                                           propname
-                                                           namespace
-                                                           at-pos
-                                                           colon-pos)))
-  "AST node for an E4X XML [expr] property-ref expression.
-The JavaScript syntax is an optional @, an optional ns::, and a name.
-
-  [ '@' ] [ name '::' ] name
-
-Examples include name, ns::name, ns::*, *::name, *::*, @attr, @ns::attr,
-@ns::*, @*::attr, @*::*, and @*.
-
-The node starts at the @ token, if present.  Otherwise it starts at the
-namespace name.  The node bounds extend through the closing right-bracket,
-or if it is missing due to a syntax error, through the end of the index
-expression."
-  propname)
-
-(put 'cl-struct-js2-xml-prop-ref-node 'js2-visitor 'js2-visit-xml-prop-ref-node)
-(put 'cl-struct-js2-xml-prop-ref-node 'js2-printer 'js2-print-xml-prop-ref-node)
-
-(defun js2-visit-xml-prop-ref-node (n v)
-  (if (js2-xml-prop-ref-node-namespace n)
-      (js2-visit-ast (js2-xml-prop-ref-node-namespace n) v))
-  (if (js2-xml-prop-ref-node-propname n)
-      (js2-visit-ast (js2-xml-prop-ref-node-propname n) v)))
-
-(defun js2-print-xml-prop-ref-node (n i)
-  (insert (js2-make-pad i))
-  (if (js2-xml-ref-node-attr-access-p n)
-      (insert "@"))
-  (when (js2-xml-prop-ref-node-namespace n)
-    (js2-print-ast (js2-xml-prop-ref-node-namespace n) 0)
-    (insert "::"))
-  (if (js2-xml-prop-ref-node-propname n)
-      (js2-print-ast (js2-xml-prop-ref-node-propname n) 0)))
-
-(defstruct (js2-xml-elem-ref-node
-            (:include js2-xml-ref-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-elem-ref-node (&key (type js2-REF_MEMBER)
-                                                           (pos js2-token-beg)
-                                                           len
-                                                           expr
-                                                           lb
-                                                           rb
-                                                           namespace
-                                                           at-pos
-                                                           colon-pos)))
-  "AST node for an E4X XML [expr] member-ref expression.
-Syntax:
-
- [ '@' ] [ name '::' ] '[' expr ']'
-
-Examples include ns::[expr], @ns::[expr], @[expr], *::[expr] and @*::[expr].
-
-Note that the form [expr] (i.e. no namespace or attribute-qualifier)
-is not a legal E4X XML element-ref expression, since it's already used
-for standard JavaScript element-get array indexing.  Hence, a
-`js2-xml-elem-ref-node' always has either the attribute-qualifier, a
-non-nil namespace node, or both.
-
-The node starts at the @ token, if present.  Otherwise it starts
-at the namespace name.  The node bounds extend through the closing
-right-bracket, or if it is missing due to a syntax error, through the
-end of the index expression."
-  expr  ; the bracketed index expression
-  lb
-  rb)
-
-(put 'cl-struct-js2-xml-elem-ref-node 'js2-visitor 'js2-visit-xml-elem-ref-node)
-(put 'cl-struct-js2-xml-elem-ref-node 'js2-printer 'js2-print-xml-elem-ref-node)
-
-(defun js2-visit-xml-elem-ref-node (n v)
-  (if (js2-xml-elem-ref-node-namespace n)
-      (js2-visit-ast (js2-xml-elem-ref-node-namespace n) v))
-  (if (js2-xml-elem-ref-node-expr n)
-      (js2-visit-ast (js2-xml-elem-ref-node-expr n) v)))
-
-(defun js2-print-xml-elem-ref-node (n i)
-  (insert (js2-make-pad i))
-  (if (js2-xml-ref-node-attr-access-p n)
-      (insert "@"))
-  (when (js2-xml-elem-ref-node-namespace n)
-    (js2-print-ast (js2-xml-elem-ref-node-namespace n) 0)
-    (insert "::"))
-  (insert "[")
-  (if (js2-xml-elem-ref-node-expr n)
-      (js2-print-ast (js2-xml-elem-ref-node-expr n) 0))
-  (insert "]"))
-
-;;; Placeholder nodes for when we try parsing the XML literals structurally.
-
-(defstruct (js2-xml-start-tag-node
-            (:include js2-xml-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-start-tag-node (&key (type js2-XML)
-                                                            (pos js2-ts-cursor)
-                                                            len
-                                                            name
-                                                            attrs
-                                                            kids
-                                                            empty-p)))
-  "AST node for an XML start-tag.  Not currently used.
-The `kids' field is a lisp list of child content nodes."
-  name      ; a `js2-xml-name-node'
-  attrs     ; a lisp list of `js2-xml-attr-node'
-  empty-p)  ; t if this is an empty element such as <foo bar="baz"/>
-
-(put 'cl-struct-js2-xml-start-tag-node 'js2-visitor 'js2-visit-xml-start-tag)
-(put 'cl-struct-js2-xml-start-tag-node 'js2-printer 'js2-print-xml-start-tag)
-
-(defun js2-visit-xml-start-tag (n v)
-  (js2-visit-ast (js2-xml-start-tag-node-name n) v)
-  (dolist (attr (js2-xml-start-tag-node-attrs n))
-    (js2-visit-ast attr v))
-  (js2-visit-block n v))
-
-(defun js2-print-xml-start-tag (n i)
-  (insert (js2-make-pad i) "<")
-  (js2-print-ast (js2-xml-start-tag-node-name n) 0)
-  (when (js2-xml-start-tag-node-attrs n)
-    (insert " ")
-    (js2-print-list (js2-xml-start-tag-node-attrs n) " "))
-  (insert ">"))
-
-;; I -think- I'm going to make the parent node the corresponding start-tag,
-;; and add the end-tag to the kids list of the parent as well.
-(defstruct (js2-xml-end-tag-node
-            (:include js2-xml-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-end-tag-node (&key (type js2-XML)
-                                                          (pos js2-ts-cursor)
-                                                          len
-                                                          name)))
-  "AST node for an XML end-tag.  Not currently used."
-  name)  ; a `js2-xml-name-node'
-
-(put 'cl-struct-js2-xml-end-tag-node 'js2-visitor 'js2-visit-xml-end-tag)
-(put 'cl-struct-js2-xml-end-tag-node 'js2-printer 'js2-print-xml-end-tag)
-
-(defun js2-visit-xml-end-tag (n v)
-  (js2-visit-ast (js2-xml-end-tag-node-name n) v))
-
-(defun js2-print-xml-end-tag (n i)
-  (insert (js2-make-pad i))
-  (insert "</")
-  (js2-print-ast (js2-xml-end-tag-node-name n) 0)
-  (insert ">"))
-
-(defstruct (js2-xml-name-node
-            (:include js2-xml-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-name-node (&key (type js2-XML)
-                                                       (pos js2-ts-cursor)
-                                                       len
-                                                       namespace
-                                                       kids)))
-  "AST node for an E4X XML name.  Not currently used.
-Any XML name can be qualified with a namespace, hence the namespace field.
-Further, any E4X name can be comprised of arbitrary JavaScript {} expressions.
-The kids field is a list of `js2-name-node' and `js2-xml-js-expr-node'.
-For a simple name, the kids list has exactly one node, a `js2-name-node'."
-  namespace)  ; a `js2-string-node'
-
-(put 'cl-struct-js2-xml-name-node 'js2-visitor 'js2-visit-xml-name-node)
-(put 'cl-struct-js2-xml-name-node 'js2-printer 'js2-print-xml-name-node)
-
-(defun js2-visit-xml-name-node (n v)
-  (js2-visit-ast (js2-xml-name-node-namespace n) v))
-
-(defun js2-print-xml-name-node (n i)
-  (insert (js2-make-pad i))
-  (when (js2-xml-name-node-namespace n)
-    (js2-print-ast (js2-xml-name-node-namespace n) 0)
-    (insert "::"))
-  (dolist (kid (js2-xml-name-node-kids n))
-    (js2-print-ast kid 0)))
-
-(defstruct (js2-xml-pi-node
-            (:include js2-xml-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-pi-node (&key (type js2-XML)
-                                                     (pos js2-ts-cursor)
-                                                     len
-                                                     name
-                                                     attrs)))
-  "AST node for an E4X XML processing instruction.  Not currently used."
-  name   ; a `js2-xml-name-node'
-  attrs) ; a list of `js2-xml-attr-node'
-
-(put 'cl-struct-js2-xml-pi-node 'js2-visitor 'js2-visit-xml-pi-node)
-(put 'cl-struct-js2-xml-pi-node 'js2-printer 'js2-print-xml-pi-node)
-
-(defun js2-visit-xml-pi-node (n v)
-  (js2-visit-ast (js2-xml-pi-node-name n) v)
-  (dolist (attr (js2-xml-pi-node-attrs n))
-    (js2-visit-ast attr v)))
-
-(defun js2-print-xml-pi-node (n i)
-  (insert (js2-make-pad i) "<?")
-  (js2-print-ast (js2-xml-pi-node-name n))
-  (when (js2-xml-pi-node-attrs n)
-    (insert " ")
-    (js2-print-list (js2-xml-pi-node-attrs n)))
-  (insert "?>"))
-
-(defstruct (js2-xml-cdata-node
-            (:include js2-xml-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-cdata-node (&key (type js2-XML)
-                                                        (pos js2-ts-cursor)
-                                                        len
-                                                        content)))
-  "AST node for a CDATA escape section.  Not currently used."
-  content)  ; a `js2-string-node' with node-property 'quote-type 'cdata
-
-(put 'cl-struct-js2-xml-cdata-node 'js2-visitor 'js2-visit-xml-cdata-node)
-(put 'cl-struct-js2-xml-cdata-node 'js2-printer 'js2-print-xml-cdata-node)
-
-(defun js2-visit-xml-cdata-node (n v)
-  (js2-visit-ast (js2-xml-cdata-node-content n) v))
-
-(defun js2-print-xml-cdata-node (n i)
-  (insert (js2-make-pad i))
-  (js2-print-ast (js2-xml-cdata-node-content n)))
-
-(defstruct (js2-xml-attr-node
-            (:include js2-xml-node)
-            (:constructor nil)
-            (:constructor make-js2-attr-node (&key (type js2-XML)
-                                                   (pos js2-ts-cursor)
-                                                   len
-                                                   name
-                                                   value
-                                                   eq-pos
-                                                   quote-type)))
-  "AST node representing a foo='bar' XML attribute value.  Not yet used."
-  name   ; a `js2-xml-name-node'
-  value  ; a `js2-xml-name-node'
-  eq-pos ; buffer position of "=" sign
-  quote-type) ; 'single or 'double
-
-(put 'cl-struct-js2-xml-attr-node 'js2-visitor 'js2-visit-xml-attr-node)
-(put 'cl-struct-js2-xml-attr-node 'js2-printer 'js2-print-xml-attr-node)
-
-(defun js2-visit-xml-attr-node (n v)
-  (js2-visit-ast (js2-xml-attr-node-name n) v)
-  (js2-visit-ast (js2-xml-attr-node-value n) v))
-
-(defun js2-print-xml-attr-node (n i)
-  (let ((quote (if (eq (js2-xml-attr-node-quote-type n) 'single)
-                   "'"
-                 "\"")))
-    (insert (js2-make-pad i))
-    (js2-print-ast (js2-xml-attr-node-name n) 0)
-    (insert "=" quote)
-    (js2-print-ast (js2-xml-attr-node-value n) 0)
-    (insert quote)))
-
-(defstruct (js2-xml-text-node
-            (:include js2-xml-node)
-            (:constructor nil)
-            (:constructor make-js2-text-node (&key (type js2-XML)
-                                                   (pos js2-ts-cursor)
-                                                   len
-                                                   content)))
-  "AST node for an E4X XML text node.  Not currently used."
-  content)  ; a lisp list of `js2-string-node' and `js2-xml-js-expr-node'
-
-(put 'cl-struct-js2-xml-text-node 'js2-visitor 'js2-visit-xml-text-node)
-(put 'cl-struct-js2-xml-text-node 'js2-printer 'js2-print-xml-text-node)
-
-(defun js2-visit-xml-text-node (n v)
-  (js2-visit-ast (js2-xml-text-node-content n) v))
-
-(defun js2-print-xml-text-node (n i)
-  (insert (js2-make-pad i))
-  (dolist (kid (js2-xml-text-node-content n))
-    (js2-print-ast kid)))
-
-(defstruct (js2-xml-comment-node
-            (:include js2-xml-node)
-            (:constructor nil)
-            (:constructor make-js2-xml-comment-node (&key (type js2-XML)
-                                                          (pos js2-ts-cursor)
-                                                          len)))
-  "AST node for E4X XML comment.  Not currently used.")
-
-(put 'cl-struct-js2-xml-comment-node 'js2-visitor 'js2-visit-none)
-(put 'cl-struct-js2-xml-comment-node 'js2-printer 'js2-print-xml-comment)
-
-(defun js2-print-xml-comment (n i)
-  (insert (js2-make-pad i)
-          (js2-node-string n)))
-
-;;; Node utilities
-
-(defsubst js2-node-line (n)
-  "Fetch the source line number at the start of node N.
-This is O(n) in the length of the source buffer; use prudently."
-  (1+ (count-lines (point-min) (js2-node-abs-pos n))))
-
-(defsubst js2-block-node-kid (n i)
-  "Return child I of node N, or nil if there aren't that many."
-  (nth i (js2-block-node-kids n)))
-
-(defsubst js2-block-node-first (n)
-  "Return first child of block node N, or nil if there is none."
-  (first (js2-block-node-kids n)))
-
-(defun js2-node-root (n)
-  "Return the root of the AST containing N.
-If N has no parent pointer, returns N."
-  (let ((parent (js2-node-parent n)))
-    (if parent
-        (js2-node-root parent)
-      n)))
-
-(defun js2-node-position-in-parent (node &optional parent)
-  "Return the position of NODE in parent's block-kids list.
-PARENT can be supplied if known.  Positioned returned is zero-indexed.
-Returns 0 if NODE is not a child of a block statement, or if NODE
-is not a statement node."
-  (let ((p (or parent (js2-node-parent node)))
-        (i 0))
-    (if (not (js2-block-node-p p))
-        i
-      (or (js2-position node (js2-block-node-kids p))
-          0))))
-
-(defsubst js2-node-short-name (n)
-  "Return the short name of node N as a string, e.g. `js2-if-node'."
-  (substring (symbol-name (aref n 0))
-             (length "cl-struct-")))
-
-(defsubst js2-node-child-list (node)
-  "Return the child list for NODE, a lisp list of nodes.
-Works for block nodes, array nodes, obj literals, funarg lists,
-var decls and try nodes (for catch clauses).  Note that you should call
-`js2-block-node-kids' on the function body for the body statements.
-Returns nil for zero-length child lists or unsupported nodes."
-  (cond
-   ((js2-function-node-p node)
-    (js2-function-node-params node))
-   ((js2-block-node-p node)
-    (js2-block-node-kids node))
-   ((js2-try-node-p node)
-    (js2-try-node-catch-clauses node))
-   ((js2-array-node-p node)
-    (js2-array-node-elems node))
-   ((js2-object-node-p node)
-    (js2-object-node-elems node))
-   ((js2-call-node-p node)
-    (js2-call-node-args node))
-   ((js2-new-node-p node)
-    (js2-new-node-args node))
-   ((js2-var-decl-node-p node)
-    (js2-var-decl-node-kids node))
-   (t
-    nil)))
-
-(defsubst js2-node-set-child-list (node kids)
-  "Set the child list for NODE to KIDS."
-   (cond
-    ((js2-function-node-p node)
-     (setf (js2-function-node-params node) kids))
-    ((js2-block-node-p node)
-     (setf (js2-block-node-kids node) kids))
-    ((js2-try-node-p node)
-     (setf (js2-try-node-catch-clauses node) kids))
-    ((js2-array-node-p node)
-     (setf (js2-array-node-elems node) kids))
-    ((js2-object-node-p node)
-     (setf (js2-object-node-elems node) kids))
-    ((js2-call-node-p node)
-     (setf (js2-call-node-args node) kids))
-    ((js2-new-node-p node)
-     (setf (js2-new-node-args node) kids))
-    ((js2-var-decl-node-p node)
-     (setf (js2-var-decl-node-kids node) kids))
-    (t
-     (error "Unsupported node type: %s" (js2-node-short-name node))))
-   kids)
-
-;; All because Common Lisp doesn't support multiple inheritance for defstructs.
-(defconst js2-paren-expr-nodes
-  '(cl-struct-js2-array-comp-loop-node
-    cl-struct-js2-array-comp-node
-    cl-struct-js2-call-node
-    cl-struct-js2-catch-node
-    cl-struct-js2-do-node
-    cl-struct-js2-elem-get-node
-    cl-struct-js2-for-in-node
-    cl-struct-js2-for-node
-    cl-struct-js2-function-node
-    cl-struct-js2-if-node
-    cl-struct-js2-let-node
-    cl-struct-js2-new-node
-    cl-struct-js2-paren-node
-    cl-struct-js2-switch-node
-    cl-struct-js2-while-node
-    cl-struct-js2-with-node
-    cl-struct-js2-xml-dot-query-node)
-  "Node types that can have a parenthesized child expression.
-In particular, nodes that respond to `js2-node-lp' and `js2-node-rp'.")
-
-(defsubst js2-paren-expr-node-p (node)
-  "Return t for nodes that typically have a parenthesized child expression.
-Useful for computing the indentation anchors for arg-lists and conditions.
-Note that it may return a false positive, for instance when NODE is
-a `js2-new-node' and there are no arguments or parentheses."
-  (memq (aref node 0) js2-paren-expr-nodes))
-
-;; Fake polymorphism... yech.
-(defsubst js2-node-lp (node)
-  "Return relative left-paren position for NODE, if applicable.
-For `js2-elem-get-node' structs, returns left-bracket position.
-Note that the position may be nil in the case of a parse error."
-  (cond
-   ((js2-elem-get-node-p node)
-    (js2-elem-get-node-lb node))
-   ((js2-loop-node-p node)
-    (js2-loop-node-lp node))
-   ((js2-function-node-p node)
-    (js2-function-node-lp node))
-   ((js2-if-node-p node)
-    (js2-if-node-lp node))
-   ((js2-new-node-p node)
-    (js2-new-node-lp node))
-   ((js2-call-node-p node)
-    (js2-call-node-lp node))
-   ((js2-paren-node-p node)
-    (js2-node-pos node))
-   ((js2-switch-node-p node)
-    (js2-switch-node-lp node))
-   ((js2-catch-node-p node)
-    (js2-catch-node-lp node))
-   ((js2-let-node-p node)
-    (js2-let-node-lp node))
-   ((js2-array-comp-node-p node)
-    (js2-array-comp-node-lp node))
-   ((js2-with-node-p node)
-    (js2-with-node-lp node))
-   ((js2-xml-dot-query-node-p node)
-    (1+ (js2-infix-node-op-pos node)))
-   (t
-    (error "Unsupported node type: %s" (js2-node-short-name node)))))
-
-;; Fake polymorphism... blech.
-(defsubst js2-node-rp (node)
-  "Return relative right-paren position for NODE, if applicable.
-For `js2-elem-get-node' structs, returns right-bracket position.
-Note that the position may be nil in the case of a parse error."
-  (cond
-   ((js2-elem-get-node-p node)
-    (js2-elem-get-node-lb node))
-   ((js2-loop-node-p node)
-    (js2-loop-node-rp node))
-   ((js2-function-node-p node)
-    (js2-function-node-rp node))
-   ((js2-if-node-p node)
-    (js2-if-node-rp node))
-   ((js2-new-node-p node)
-    (js2-new-node-rp node))
-   ((js2-call-node-p node)
-    (js2-call-node-rp node))
-   ((js2-paren-node-p node)
-    (+ (js2-node-pos node) (js2-node-len node)))
-   ((js2-switch-node-p node)
-    (js2-switch-node-rp node))
-   ((js2-catch-node-p node)
-    (js2-catch-node-rp node))
-   ((js2-let-node-p node)
-    (js2-let-node-rp node))
-   ((js2-array-comp-node-p node)
-    (js2-array-comp-node-rp node))
-   ((js2-with-node-p node)
-    (js2-with-node-rp node))
-   ((js2-xml-dot-query-node-p node)
-    (1+ (js2-xml-dot-query-node-rp node)))
-   (t
-    (error "Unsupported node type: %s" (js2-node-short-name node)))))
-
-(defsubst js2-node-first-child (node)
-  "Returns the first element of `js2-node-child-list' for NODE."
-  (car (js2-node-child-list node)))
-
-(defsubst js2-node-last-child (node)
-  "Returns the last element of `js2-node-last-child' for NODE."
-  (car (last (js2-node-child-list node))))
-
-(defun js2-node-prev-sibling (node)
-  "Return the previous statement in parent.
-Works for parents supported by `js2-node-child-list'.
-Returns nil if NODE is not in the parent, or PARENT is
-not a supported node, or if NODE is the first child."
-  (let* ((p (js2-node-parent node))
-         (kids (js2-node-child-list p))
-         (sib (car kids)))
-    (while (and kids
-                (neq node (cadr kids)))
-      (setq kids (cdr kids)
-            sib (car kids)))
-    sib))
-
-(defun js2-node-next-sibling (node)
-  "Return the next statement in parent block.
-Returns nil if NODE is not in the block, or PARENT is not
-a block node, or if NODE is the last statement."
-  (let* ((p (js2-node-parent node))
-         (kids (js2-node-child-list p)))
-    (while (and kids
-                (neq node (car kids)))
-      (setq kids (cdr kids)))
-    (cadr kids)))
-
-(defun js2-node-find-child-before (pos parent &optional after)
-  "Find the last child that starts before POS in parent.
-If AFTER is non-nil, returns first child starting after POS.
-POS is an absolute buffer position.  PARENT is any node
-supported by `js2-node-child-list'.
-Returns nil if no applicable child is found."
-  (let ((kids (if (js2-function-node-p parent)
-                  (js2-block-node-kids (js2-function-node-body parent))
-                (js2-node-child-list parent)))
-        (beg (if (js2-function-node-p parent)
-                 (js2-node-abs-pos (js2-function-node-body parent))
-               (js2-node-abs-pos parent)))
-        kid
-        result
-        fn
-        (continue t))
-    (setq fn (if after '> '<))
-    (while (and kids continue)
-      (setq kid (car kids))
-      (if (funcall fn (+ beg (js2-node-pos kid)) pos)
-          (setq result kid
-                continue (if after nil t))
-        (setq continue (if after t nil)))
-      (setq kids (cdr kids)))
-    result))
-
-(defun js2-node-find-child-after (pos parent)
-  "Find first child that starts after POS in parent.
-POS is an absolute buffer position.  PARENT is any node
-supported by `js2-node-child-list'.
-Returns nil if no applicable child is found."
-  (js2-node-find-child-before pos parent 'after))
-
-(defun js2-node-replace-child (pos parent new-node)
-  "Replace node at index POS in PARENT with NEW-NODE.
-Only works for parents supported by `js2-node-child-list'."
-  (let ((kids (js2-node-child-list parent))
-        (i 0))
-    (while (< i pos)
-      (setq kids (cdr kids)
-            i (1+ i)))
-    (setcar kids new-node)
-    (js2-node-add-children parent new-node)))
-
-(defun js2-node-buffer (n)
-  "Return the buffer associated with AST N.
-Returns nil if the buffer is not set as a property on the root
-node, or if parent links were not recorded during parsing."
-  (let ((root (js2-node-root n)))
-    (and root
-         (js2-ast-root-p root)
-         (js2-ast-root-buffer root))))
-
-(defsubst js2-block-node-push (n kid)
-  "Push js2-node KID onto the end of js2-block-node N's child list.
-KID is always added to the -end- of the kids list.
-Function also calls `js2-node-add-children' to add the parent link."
-  (let ((kids (js2-node-child-list n)))
-    (if kids
-        (setcdr kids (nconc (cdr kids) (list kid)))
-      (js2-node-set-child-list n (list kid)))
-    (js2-node-add-children n kid)))
-
-(defun js2-node-string (node)
-  (let ((buf (js2-node-buffer node))
-        pos)
-    (unless buf
-      (error "No buffer available for node %s" node))
-    (save-excursion
-      (set-buffer buf)
-      (buffer-substring-no-properties (setq pos (js2-node-abs-pos node))
-                                      (+ pos (js2-node-len node))))))
-
-;; Container for storing the node we're looking for in a traversal.
-(defvar js2-discovered-node nil)
-(make-variable-buffer-local 'js2-discovered-node)
-
-;; Keep track of absolute node position during traversals.
-(defvar js2-visitor-offset nil)
-(make-variable-buffer-local 'js2-visitor-offset)
-
-(defvar js2-node-search-point nil)
-(make-variable-buffer-local 'js2-node-search-point)
-
-(when js2-mode-dev-mode-p
-  (defun js2-find-node-at-point ()
-    (interactive)
-    (let ((node (js2-node-at-point)))
-      (message "%s" (or node "No node found at point"))))
-  (defun js2-node-name-at-point ()
-    (interactive)
-    (let ((node (js2-node-at-point)))
-      (message "%s" (if node
-                        (js2-node-short-name node)
-                      "No node found at point.")))))
-
-(defun js2-node-at-point (&optional pos skip-comments)
-  "Return AST node at POS, a buffer position, defaulting to current point.
-The `js2-mode-ast' variable must be set to the current parse tree.
-Signals an error if the AST (`js2-mode-ast') is nil.
-Always returns a node - if it can't find one, it returns the root.
-If SKIP-COMMENTS is non-nil, comment nodes are ignored."
-  (let ((ast js2-mode-ast)
-        result)
-    (unless ast
-      (error "No JavaScript AST available"))
-    ;; Look through comments first, since they may be inside nodes that
-    ;; would otherwise report a match.
-    (setq pos (or pos (point))
-          result (if (> pos (js2-node-abs-end ast))
-                     ast
-                   (if (not skip-comments)
-                       (js2-comment-at-point pos))))
-    (unless result
-      (setq js2-discovered-node nil
-            js2-visitor-offset 0
-            js2-node-search-point pos)
-      (unwind-protect
-          (catch 'js2-visit-done
-            (js2-visit-ast ast #'js2-node-at-point-visitor))
-        (setq js2-visitor-offset nil
-              js2-node-search-point nil))
-      (setq result js2-discovered-node))
-    ;; may have found a comment beyond end of last child node,
-    ;; since visiting the ast-root looks at the comment-list last.
-    (if (and skip-comments
-             (js2-comment-node-p result))
-        (setq result nil))
-    (or result js2-mode-ast)))
-
-(defun js2-node-at-point-visitor (node end-p)
-  (let ((rel-pos (js2-node-pos node))
-        abs-pos
-        abs-end
-        (point js2-node-search-point))
-    (cond
-     (end-p
-      ;; this evaluates to a non-nil return value, even if it's zero
-      (decf js2-visitor-offset rel-pos))
-     ;; we already looked for comments before visiting, and don't want them now
-     ((js2-comment-node-p node)
-      nil)
-     (t
-      (setq abs-pos (incf js2-visitor-offset rel-pos)
-            ;; we only want to use the node if the point is before
-            ;; the last character position in the node, so we decrement
-            ;; the absolute end by 1.
-            abs-end (+ abs-pos (js2-node-len node) -1))
-      (cond
-       ;; If this node starts after search-point, stop the search.
-       ((> abs-pos point)
-        (throw 'js2-visit-done nil))
-       ;; If this node ends before the search-point, don't check kids.
-       ((> point abs-end)
-        nil)
-       (t
-        ;; Otherwise point is within this node, possibly in a child.
-        (setq js2-discovered-node node)
-        t))))))  ; keep processing kids to look for more specific match
-
-(defsubst js2-block-comment-p (node)
-  "Return non-nil if NODE is a comment node of format `jsdoc' or `block'."
-  (and (js2-comment-node-p node)
-       (memq (js2-comment-node-format node) '(jsdoc block))))
-
-;; TODO:  put the comments in a vector and binary-search them instead
-(defun js2-comment-at-point (&optional pos)
-  "Look through scanned comment nodes for one containing POS.
-POS is a buffer position that defaults to current point.
-Function returns nil if POS was not in any comment node."
-  (let ((ast js2-mode-ast)
-        (x (or pos (point)))
-        beg
-        end)
-    (unless ast
-      (error "No JavaScript AST available"))
-    (catch 'done
-      ;; Comments are stored in lexical order.
-      (dolist (comment (js2-ast-root-comments ast) nil)
-        (setq beg (js2-node-abs-pos comment)
-              end (+ beg (js2-node-len comment)))
-        (if (and (>= x beg)
-                 (<= x end))
-            (throw 'done comment))))))
-
-(defun js2-mode-find-parent-fn (node)
-  "Find function enclosing NODE.
-Returns nil if NODE is not inside a function."
-  (setq node (js2-node-parent node))
-  (while (and node (not (js2-function-node-p node)))
-    (setq node (js2-node-parent node)))
-  (and (js2-function-node-p node) node))
-
-(defun js2-mode-find-enclosing-fn (node)
-  "Find function or root enclosing NODE."
-  (if (js2-ast-root-p node)
-      node
-    (setq node (js2-node-parent node))
-    (while (not (or (js2-ast-root-p node)
-                    (js2-function-node-p node)))
-      (setq node (js2-node-parent node)))
-    node))
-
-(defun js2-mode-find-enclosing-node (beg end)
-  "Find script or function fully enclosing BEG and END."
-  (let ((node (js2-node-at-point beg))
-        pos
-        (continue t))
-    (while continue
-      (if (or (js2-ast-root-p node)
-              (and (js2-function-node-p node)
-                   (<= (setq pos (js2-node-abs-pos node)) beg)
-                   (>= (+ pos (js2-node-len node)) end)))
-          (setq continue nil)
-        (setq node (js2-node-parent node))))
-    node))
-
-(defun js2-node-parent-script-or-fn (node)
-  "Find script or function immediately enclosing NODE.
-If NODE is the ast-root, returns nil."
-  (if (js2-ast-root-p node)
-      nil
-    (setq node (js2-node-parent node))
-    (while (and node (not (or (js2-function-node-p node)
-                              (js2-script-node-p node))))
-      (setq node (js2-node-parent node)))
-    node))
-
-(defsubst js2-nested-function-p (node)
-  "Return t if NODE is a nested function, or is inside a nested function."
-  (js2-function-node-p (if (js2-function-node-p node)
-                           (js2-node-parent-script-or-fn node)
-                         (js2-node-parent-script-or-fn
-                          (js2-node-parent-script-or-fn node)))))
-
-(defsubst js2-mode-shift-kids (kids start offset)
-  (dolist (kid kids)
-    (if (> (js2-node-pos kid) start)
-        (incf (js2-node-pos kid) offset))))
-
-(defsubst js2-mode-shift-children (parent start offset)
-  "Update start-positions of all children of PARENT beyond START."
-  (let ((root (js2-node-root parent)))
-    (js2-mode-shift-kids (js2-node-child-list parent) start offset)
-    (js2-mode-shift-kids (js2-ast-root-comments root) start offset)))
-
-(defsubst js2-node-is-descendant (node ancestor)
-  "Return t if NODE is a descendant of ANCESTOR."
-  (while (and node
-              (neq node ancestor))
-    (setq node (js2-node-parent node)))
-  node)
-
-;;; visitor infrastructure
-
-(defun js2-visit-none (node callback)
-  "Visitor for AST node that have no node children."
-  nil)
-
-(defun js2-print-none (node indent)
-  "Visitor for AST node with no printed representation.")
-
-(defun js2-print-body (node indent)
-  "Print a statement, or a block without braces."
-  (if (js2-block-node-p node)
-      (dolist (kid (js2-block-node-kids node))
-        (js2-print-ast kid indent))
-    (js2-print-ast node indent)))
-
-(defun js2-print-list (args &optional delimiter)
-  (loop with len = (length args)
-        for arg in args
-        for count from 1
-        do
-        (js2-print-ast arg 0)
-        (if (< count len)
-            (insert (or delimiter ", ")))))
-
-(defun js2-print-tree (ast)
-  "Prints an AST to the current buffer.
-Makes `js2-ast-parent-nodes' available to the printer functions."
-  (let ((max-lisp-eval-depth (max max-lisp-eval-depth 1500)))
-    (js2-print-ast ast)))
-
-(defun js2-print-ast (node &optional indent)
-  "Helper function for printing AST nodes.
-Requires `js2-ast-parent-nodes' to be non-nil.
-You should use `js2-print-tree' instead of this function."
-  (let ((printer (get (aref node 0) 'js2-printer))
-        (i (or indent 0))
-        (pos (js2-node-abs-pos node)))
-    ;; TODO:  wedge comments in here somewhere
-    (if printer
-        (funcall printer node i))))
-
-(defconst js2-side-effecting-tokens
-  (let ((tokens (make-bool-vector js2-num-tokens nil)))
-    (dolist (tt (list js2-ASSIGN
-                      js2-ASSIGN_ADD
-                      js2-ASSIGN_BITAND
-                      js2-ASSIGN_BITOR
-                      js2-ASSIGN_BITXOR
-                      js2-ASSIGN_DIV
-                      js2-ASSIGN_LSH
-                      js2-ASSIGN_MOD
-                      js2-ASSIGN_MUL
-                      js2-ASSIGN_RSH
-                      js2-ASSIGN_SUB
-                      js2-ASSIGN_URSH
-                      js2-BLOCK
-                      js2-BREAK
-                      js2-CALL
-                      js2-CATCH
-                      js2-CATCH_SCOPE
-                      js2-CONST
-                      js2-CONTINUE
-                      js2-DEBUGGER
-                      js2-DEC
-                      js2-DELPROP
-                      js2-DEL_REF
-                      js2-DO
-                      js2-ELSE
-                      js2-EMPTY
-                      js2-ENTERWITH
-                      js2-EXPORT
-                      js2-EXPR_RESULT
-                      js2-FINALLY
-                      js2-FOR
-                      js2-FUNCTION
-                      js2-GOTO
-                      js2-IF
-                      js2-IFEQ
-                      js2-IFNE
-                      js2-IMPORT
-                      js2-INC
-                      js2-JSR
-                      js2-LABEL
-                      js2-LEAVEWITH
-                      js2-LET
-                      js2-LETEXPR
-                      js2-LOCAL_BLOCK
-                      js2-LOOP
-                      js2-NEW
-                      js2-REF_CALL
-                      js2-RETHROW
-                      js2-RETURN
-                      js2-RETURN_RESULT
-                      js2-SEMI
-                      js2-SETELEM
-                      js2-SETELEM_OP
-                      js2-SETNAME
-                      js2-SETPROP
-                      js2-SETPROP_OP
-                      js2-SETVAR
-                      js2-SET_REF
-                      js2-SET_REF_OP
-                      js2-SWITCH
-                      js2-TARGET
-                      js2-THROW
-                      js2-TRY
-                      js2-VAR
-                      js2-WHILE
-                      js2-WITH
-                      js2-WITHEXPR
-                      js2-YIELD))
-      (aset tokens tt t))
-    (if js2-instanceof-has-side-effects
-        (aset tokens js2-INSTANCEOF t))
-    tokens))
-
-(defun js2-node-has-side-effects (node)
-  "Return t if NODE has side effects."
-  (when node  ; makes it easier to handle malformed expressions
-    (let ((tt (js2-node-type node)))
-      (cond
-       ;; This doubtless needs some work, since EXPR_VOID is used
-       ;; in several ways in Rhino, and I may not have caught them all.
-       ;; I'll wait for people to notice incorrect warnings.
-       ((and (= tt js2-EXPR_VOID)
-             (js2-expr-stmt-node-p node)) ; but not if EXPR_RESULT
-        (js2-node-has-side-effects (js2-expr-stmt-node-expr node)))
-
-       ((= tt js2-COMMA)
-        (js2-node-has-side-effects (js2-infix-node-right node)))
-
-       ((or (= tt js2-AND)
-            (= tt js2-OR))
-        (or (js2-node-has-side-effects (js2-infix-node-right node))
-            (js2-node-has-side-effects (js2-infix-node-left node))))
-
-       ((= tt js2-HOOK)
-        (and (js2-node-has-side-effects (js2-cond-node-true-expr node))
-             (js2-node-has-side-effects (js2-cond-node-false-expr node))))
-
-       ((js2-paren-node-p node)
-        (js2-node-has-side-effects (js2-paren-node-expr node)))
-
-       ((= tt js2-ERROR) ; avoid cascaded error messages
-        nil)
-       (t
-        (aref js2-side-effecting-tokens tt))))))
-
-(defun js2-member-expr-leftmost-name (node)
-  "For an expr such as foo.bar.baz, return leftmost node foo.
-NODE is any `js2-node' object.  If it represents a member expression,
-which is any sequence of property gets, element-gets, function calls,
-or xml descendants/filter operators, then we look at the lexically
-leftmost (first) node in the chain.  If it is a name-node we return it.
-Note that NODE can be a raw name-node and it will be returned as well.
-If NODE is not a name-node or member expression, or if it is a member
-expression whose leftmost target is not a name node, returns nil."
-  (let ((continue t)
-        result)
-    (while (and continue (not result))
-      (cond
-       ((js2-name-node-p node)
-        (setq result node))
-       ((js2-prop-get-node-p node)
-        (setq node (js2-prop-get-node-left node)))
-       ;; TODO:  handle call-nodes, xml-nodes, others?
-       (t
-        (setq continue nil))))
-    result))
-
-(defconst js2-stmt-node-types
-  (list js2-BLOCK
-        js2-BREAK
-        js2-CONTINUE
-        js2-DEFAULT  ; e4x "default xml namespace" statement
-        js2-DO
-        js2-EXPR_RESULT
-        js2-EXPR_VOID
-        js2-FOR
-        js2-IF
-        js2-RETURN
-        js2-SWITCH
-        js2-THROW
-        js2-TRY
-        js2-WHILE
-        js2-WITH)
-  "Node types that only appear in statement contexts.
-The list does not include nodes that always appear as the child
-of another specific statement type, such as switch-cases,
-catch and finally blocks, and else-clauses.  The list also excludes
-nodes like yield, let and var, which may appear in either expression
-or statement context, and in the latter context always have a
-`js2-expr-stmt-node' parent.  Finally, the list does not include
-functions or scripts, which are treated separately from statements
-by the JavaScript parser and runtime.")
-
-(defun js2-stmt-node-p (node)
-  "Heuristic for figuring out if NODE is a statement.
-Some node types can appear in either an expression context or a
-statement context, e.g. let-nodes, yield-nodes, and var-decl nodes.
-For these node types in a statement context, the parent will be a
-`js2-expr-stmt-node'.
-Functions aren't included in the check."
-  (memq (js2-node-type node) js2-stmt-node-types))
-
-(defsubst js2-mode-find-first-stmt (node)
-  "Search upward starting from NODE looking for a statement.
-For purposes of this function, a `js2-function-node' counts."
-  (while (not (or (js2-stmt-node-p node)
-                  (js2-function-node-p node)))
-    (setq node (js2-node-parent node)))
-  node)
-
-(defun js2-node-parent-stmt (node)
-  "Return the node's first ancestor that is a statement.
-Returns nil if NODE is a `js2-ast-root'.  Note that any expression
-appearing in a statement context will have a parent that is a
-`js2-expr-stmt-node' that will be returned by this function."
-  (let ((parent (js2-node-parent node)))
-    (if (or (null parent)
-            (js2-stmt-node-p parent)
-            (and (js2-function-node-p parent)
-                 (neq (js2-function-node-form parent) 'FUNCTION_EXPRESSION)))
-        parent
-      (js2-node-parent-stmt parent))))
-
-;; Roshan James writes:
-;;  Does consistent-return analysis on the function body when strict mode is
-;;  enabled.
-;;
-;;    function (x) { return (x+1) }
-;;
-;;  is ok, but
-;;
-;;    function (x) { if (x < 0) return (x+1); }
-;;
-;;  is not because the function can potentially return a value when the
-;;  condition is satisfied and if not, the function does not explicitly
-;;  return a value.
-;;
-;;  This extends to checking mismatches such as "return" and "return <value>"
-;;  used in the same function. Warnings are not emitted if inconsistent
-;;  returns exist in code that can be statically shown to be unreachable.
-;;  Ex.
-;;    function (x) { while (true) { ... if (..) { return value } ... } }
-;;
-;;  emits no warning. However if the loop had a break statement, then a
-;;  warning would be emitted.
-;;
-;;  The consistency analysis looks at control structures such as loops, ifs,
-;;  switch, try-catch-finally blocks, examines the reachable code paths and
-;;  warns the user about an inconsistent set of termination possibilities.
-;;
-;;  These flags enumerate the possible ways a statement/function can
-;;  terminate. These flags are used by endCheck() and by the Parser to
-;;  detect inconsistent return usage.
-;;
-;;  END_UNREACHED is reserved for code paths that are assumed to always be
-;;  able to execute (example: throw, continue)
-;;
-;;  END_DROPS_OFF indicates if the statement can transfer control to the
-;;  next one. Statement such as return dont. A compound statement may have
-;;  some branch that drops off control to the next statement.
-;;
-;;  END_RETURNS indicates that the statement can return with no value.
-;;  END_RETURNS_VALUE indicates that the statement can return a value.
-;;
-;;  A compound statement such as
-;;  if (condition) {
-;;    return value;
-;;  }
-;;  Will be detected as (END_DROPS_OFF | END_RETURN_VALUE) by endCheck()
-
-(defconst js2-END_UNREACHED 0)
-(defconst js2-END_DROPS_OFF 1)
-(defconst js2-END_RETURNS 2)
-(defconst js2-END_RETURNS_VALUE 4)
-(defconst js2-END_YIELDS 8)
-
-(defun js2-has-consistent-return-usage (node)
-  "Check that every return usage in a function body is consistent.
-Returns t if the function satisfies strict mode requirement."
-  (let ((n (js2-end-check node)))
-    ;; either it doesn't return a value in any branch...
-    (or (js2-flag-not-set-p n js2-END_RETURNS_VALUE)
-        ;; or it returns a value (or is unreached) at every branch
-        (js2-flag-not-set-p n (logior js2-END_DROPS_OFF
-                                      js2-END_RETURNS
-                                      js2-END_YIELDS)))))
-
-(defun js2-end-check-if (node)
-  "Returns in the then and else blocks must be consistent with each other.
-If there is no else block, then the return statement can fall through.
-Returns logical OR of END_* flags"
-  (let ((th (js2-if-node-then-part node))
-        (el (js2-if-node-else-part node)))
-    (if (null th)
-        js2-END_UNREACHED
-      (logior (js2-end-check th) (if el
-                                     (js2-end-check el)
-                                   js2-END_DROPS_OFF)))))
-
-(defun js2-end-check-switch (node)
-  "Consistency of return statements is checked between the case statements.
-If there is no default, then the switch can fall through. If there is a
-default, we check to see if all code paths in the default return or if
-there is a code path that can fall through.
-Returns logical OR of END_* flags."
-  (let ((rv js2-END_UNREACHED)
-        default-case)
-    ;; examine the cases
-    (catch 'break
-      (dolist (c (js2-switch-node-cases node))
-        (if (js2-case-node-expr c)
-            (js2-set-flag rv (js2-end-check-block c))
-          (setq default-case c)
-          (throw 'break nil))))
-
-    ;; we don't care how the cases drop into each other
-    (js2-clear-flag rv js2-END_DROPS_OFF)
-
-    ;; examine the default
-    (js2-set-flag rv (if default-case
-                         (js2-end-check default-case)
-                       js2-END_DROPS_OFF))
-    rv))
-
-(defun js2-end-check-try (node)
- "If the block has a finally, return consistency is checked in the
-finally block. If all code paths in the finally return, then the
-returns in the try-catch blocks don't matter. If there is a code path
-that does not return or if there is no finally block, the returns
-of the try and catch blocks are checked for mismatch.
-Returns logical OR of END_* flags."
- (let ((finally (js2-try-node-finally-block node))
-       rv)
-   ;; check the finally if it exists
-   (setq rv (if finally
-                (js2-end-check (js2-finally-node-body finally))
-              js2-END_DROPS_OFF))
-
-   ;; If the finally block always returns, then none of the returns
-   ;; in the try or catch blocks matter.
-   (when (js2-flag-set-p rv js2-END_DROPS_OFF)
-     (js2-clear-flag rv js2-END_DROPS_OFF)
-
-     ;; examine the try block
-     (js2-set-flag rv (js2-end-check (js2-try-node-try-block node)))
-
-     ;; check each catch block
-     (dolist (cb (js2-try-node-catch-clauses node))
-       (js2-set-flag rv (js2-end-check (js2-catch-node-block cb)))))
-   rv))
-
-(defun js2-end-check-loop (node)
-  "Return statement in the loop body must be consistent. The default
-assumption for any kind of a loop is that it will eventually terminate.
-The only exception is a loop with a constant true condition. Code that
-follows such a loop is examined only if one can statically determine
-that there is a break out of the loop.
-
-    for(... ; ... ; ...) {}
-    for(... in ... ) {}
-    while(...) { }
-    do { } while(...)
-
-Returns logical OR of END_* flags."
-  (let ((rv (js2-end-check (js2-loop-node-body node)))
-        (condition (cond
-                    ((js2-while-node-p node)
-                     (js2-while-node-condition node))
-                     ((js2-do-node-p node)
-                      (js2-do-node-condition node))
-                     ((js2-for-node-p node)
-                      (js2-for-node-condition node)))))
-
-    ;; check to see if the loop condition is always true
-    (if (and condition
-             (eq (js2-always-defined-boolean-p condition) 'ALWAYS_TRUE))
-        (js2-clear-flag rv js2-END_DROPS_OFF))
-
-    ;; look for effect of breaks
-    (js2-set-flag rv (js2-node-get-prop node
-                                        'CONTROL_BLOCK_PROP
-                                        js2-END_UNREACHED))
-    rv))
-
-(defun js2-end-check-block (node)
-  "A general block of code is examined statement by statement.
-If any statement (even a compound one) returns in all branches, then
-subsequent statements are not examined.
-Returns logical OR of END_* flags."
-  (let* ((rv js2-END_DROPS_OFF)
-         (kids (js2-block-node-kids node))
-         (n (car kids)))
-    ;; Check each statment.  If the statement can continue onto the next
-    ;; one (i.e. END_DROPS_OFF is set), then check the next statement.
-    (while (and n (js2-flag-set-p rv js2-END_DROPS_OFF))
-      (js2-clear-flag rv js2-END_DROPS_OFF)
-      (js2-set-flag rv (js2-end-check n))
-      (setq kids (cdr kids)
-            n (car kids)))
-    rv))
-
-(defun js2-end-check-label (node)
-  "A labeled statement implies that there may be a break to the label.
-The function processes the labeled statement and then checks the
-CONTROL_BLOCK_PROP property to see if there is ever a break to the
-particular label.
-Returns logical OR of END_* flags."
-  (let ((rv (js2-end-check (js2-labeled-stmt-node-stmt node))))
-    (logior rv (js2-node-get-prop node
-                                  'CONTROL_BLOCK_PROP
-                                  js2-END_UNREACHED))))
-
-(defun js2-end-check-break (node)
-  "When a break is encountered annotate the statement being broken
-out of by setting its CONTROL_BLOCK_PROP property.
-Returns logical OR of END_* flags."
-  (and (js2-break-node-target node)
-       (js2-node-set-prop (js2-break-node-target node)
-                          'CONTROL_BLOCK_PROP
-                          js2-END_DROPS_OFF))
-  js2-END_UNREACHED)
-
-(defun js2-end-check (node)
-  "Examine the body of a function, doing a basic reachability analysis.
-Returns a combination of flags END_* flags that indicate
-how the function execution can terminate. These constitute only the
-pessimistic set of termination conditions. It is possible that at
-runtime certain code paths will never be actually taken. Hence this
-analysis will flag errors in cases where there may not be errors.
-Returns logical OR of END_* flags"
-  (let (kid)
-    (cond
-     ((js2-break-node-p node)
-      (js2-end-check-break node))
-
-     ((js2-expr-stmt-node-p node)
-      (if (setq kid (js2-expr-stmt-node-expr node))
-          (js2-end-check kid)
-        js2-END_DROPS_OFF))
-
-     ((or (js2-continue-node-p node)
-          (js2-throw-node-p node))
-      js2-END_UNREACHED)
-
-     ((js2-return-node-p node)
-      (if (setq kid (js2-return-node-retval node))
-          js2-END_RETURNS_VALUE
-        js2-END_RETURNS))
-
-     ((js2-loop-node-p node)
-      (js2-end-check-loop node))
-
-     ((js2-switch-node-p node)
-      (js2-end-check-switch node))
-
-     ((js2-labeled-stmt-node-p node)
-      (js2-end-check-label node))
-
-     ((js2-if-node-p node)
-      (js2-end-check-if node))
-
-     ((js2-try-node-p node)
-      (js2-end-check-try node))
-
-     ((js2-block-node-p node)
-      (if (null (js2-block-node-kids node))
-          js2-END_DROPS_OFF
-        (js2-end-check-block node)))
-
-     ((js2-yield-node-p node)
-      js2-END_YIELDS)
-
-     (t
-      js2-END_DROPS_OFF))))
-
-(defun js2-always-defined-boolean-p (node)
-  "Check if NODE always evaluates to true or false in boolean context.
-Returns 'ALWAYS_TRUE, 'ALWAYS_FALSE, or nil if it's neither always true
-nor always false."
-  (let ((tt (js2-node-type node))
-        num)
-    (cond
-     ((or (= tt js2-FALSE) (= tt js2-NULL))
-      'ALWAYS_FALSE)
-     ((= tt js2-TRUE)
-      'ALWAYS_TRUE)
-     ((= tt js2-NUMBER)
-      (setq num (js2-number-node-num-value node))
-      (if (and (not (eq num 0.0e+NaN))
-               (not (zerop num)))
-          'ALWAYS_TRUE
-        'ALWAYS_FALSE))
-     (t
-      nil))))
-
-(provide 'js2-ast)
-
-;;; js2-ast.el ends here
-;;; js2-highlight.el --- JavaScript syntax coloring support
-
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Keywords:  javascript languages
-
-;;; Code:
-
-
-(defsubst js2-set-face (beg end face &optional record)
-  "Fontify a region.  If RECORD is non-nil, record for later."
-  (when (plusp js2-highlight-level)
-    (setq beg (min (point-max) beg)
-          beg (max (point-min) beg)
-          end (min (point-max) end)
-          end (max (point-min) end))
-    (if record
-        (push (list beg end face) js2-mode-fontifications)
-      (put-text-property beg end 'face face))))
-
-(defsubst js2-set-kid-face (pos kid len face)
-  "Set-face on a child node.
-POS is absolute buffer position of parent.
-KID is the child node.
-LEN is the length to fontify.
-FACE is the face to fontify with."
-  (js2-set-face (+ pos (js2-node-pos kid))
-                (+ pos (js2-node-pos kid) (js2-node-len kid))
-                face))
-
-(defsubst js2-fontify-kwd (start length)
-  (js2-set-face start (+ start length) 'font-lock-keyword-face))
-
-(defsubst js2-clear-face (beg end)
-  (remove-text-properties beg end '(face nil
-                                    help-echo nil
-                                    point-entered nil
-                                    c-in-sws nil)))
-
-(defsubst js2-record-text-property (beg end prop value)
-  "Record a text property to set when parsing finishes."
-  (push (list beg end prop value) js2-mode-deferred-properties))
-
-(defconst js2-ecma-global-props
-  (concat "^"
-          (regexp-opt
-           '("Infinity" "NaN" "undefined" "arguments") t)
-          "$")
-  "Value properties of the Ecma-262 Global Object.
-Shown at or above `js2-highlight-level' 2.")
-
-;; might want to add the name "arguments" to this list?
-(defconst js2-ecma-object-props
-  (concat "^"
-          (regexp-opt
-           '("prototype" "__proto__" "__parent__") t)
-          "$")
-  "Value properties of the Ecma-262 Object constructor.
-Shown at or above `js2-highlight-level' 2.")
-
-(defconst js2-ecma-global-funcs
-  (concat
-   "^"
-   (regexp-opt
-    '("decodeURI" "decodeURIComponent" "encodeURI" "encodeURIComponent"
-      "eval" "isFinite" "isNaN" "parseFloat" "parseInt") t)
-   "$")
-  "Function properties of the Ecma-262 Global object.
-Shown at or above `js2-highlight-level' 2.")
-
-(defconst js2-ecma-number-props
-  (concat "^"
-          (regexp-opt '("MAX_VALUE" "MIN_VALUE" "NaN"
-                        "NEGATIVE_INFINITY"
-                        "POSITIVE_INFINITY") t)
-          "$")
-  "Properties of the Ecma-262 Number constructor.
-Shown at or above `js2-highlight-level' 2.")
-
-(defconst js2-ecma-date-props "^\\(parse\\|UTC\\)$"
-  "Properties of the Ecma-262 Date constructor.
-Shown at or above `js2-highlight-level' 2.")
-
-
-(defconst js2-ecma-math-props
-  (concat "^"
-          (regexp-opt
-           '("E" "LN10" "LN2" "LOG2E" "LOG10E" "PI" "SQRT1_2" "SQRT2")
-           t)
-          "$")
-  "Properties of the Ecma-262 Math object.
-Shown at or above `js2-highlight-level' 2.")
-
-
-(defconst js2-ecma-math-funcs
-  (concat "^"
-          (regexp-opt
-           '("abs" "acos" "asin" "atan" "atan2" "ceil" "cos" "exp" "floor"
-             "log" "max" "min" "pow" "random" "round" "sin" "sqrt" "tan") t)
-          "$")
-  "Function properties of the Ecma-262 Math object.
-Shown at or above `js2-highlight-level' 2.")
-
-(defconst js2-ecma-function-props
-  (concat
-   "^"
-   (regexp-opt
-    '(;; properties of the Object prototype object
-      "hasOwnProperty" "isPrototypeOf" "propertyIsEnumerable"
-      "toLocaleString" "toString" "valueOf"
-      ;; properties of the Function prototype object
-      "apply" "call"
-      ;; properties of the Array prototype object
-      "concat" "join" "pop" "push" "reverse" "shift" "slice" "sort"
-      "splice" "unshift"
-      ;; properties of the String prototype object
-      "charAt" "charCodeAt" "fromCharCode" "indexOf" "lastIndexOf"
-      "localeCompare" "match" "replace" "search" "split" "substring"
-      "toLocaleLowerCase" "toLocaleUpperCase" "toLowerCase"
-      "toUpperCase"
-      ;; properties of the Number prototype object
-      "toExponential" "toFixed" "toPrecision"
-      ;; properties of the Date prototype object
-      "getDate" "getDay" "getFullYear" "getHours" "getMilliseconds"
-      "getMinutes" "getMonth" "getSeconds" "getTime"
-      "getTimezoneOffset" "getUTCDate" "getUTCDay" "getUTCFullYear"
-      "getUTCHours" "getUTCMilliseconds" "getUTCMinutes" "getUTCMonth"
-      "getUTCSeconds" "setDate" "setFullYear" "setHours"
-      "setMilliseconds" "setMinutes" "setMonth" "setSeconds" "setTime"
-      "setUTCDate" "setUTCFullYear" "setUTCHours" "setUTCMilliseconds"
-      "setUTCMinutes" "setUTCMonth" "setUTCSeconds" "toDateString"
-      "toLocaleDateString" "toLocaleString" "toLocaleTimeString"
-      "toTimeString" "toUTCString"
-      ;; properties of the RegExp prototype object
-      "exec" "test"
-      ;; SpiderMonkey/Rhino extensions, versions 1.5+
-      "toSource" "__defineGetter__" "__defineSetter__"
-      "__lookupGetter__" "__lookupSetter__" "__noSuchMethod__"
-      "every" "filter" "forEach" "lastIndexOf" "map" "some")
-    t)
-   "$")
-  "Built-in functions defined by Ecma-262 and SpiderMonkey extensions.
-Shown at or above `js2-highlight-level' 3.")
-
-(defsubst js2-parse-highlight-prop-get (parent target prop call-p)
-  (let ((target-name (and target
-                          (js2-name-node-p target)
-                          (js2-name-node-name target)))
-        (prop-name (if prop (js2-name-node-name prop)))
-        (level1 (>= js2-highlight-level 1))
-        (level2 (>= js2-highlight-level 2))
-        (level3 (>= js2-highlight-level 3))
-        pos
-        face)
-    (when level2
-      (if call-p
-          (cond
-           ((and target prop)
-            (cond
-             ((and level3 (string-match js2-ecma-function-props prop-name))
-              (setq face 'font-lock-builtin-face))
-             ((and target-name prop)
-              (cond
-               ((string= target-name "Date")
-                (if (string-match js2-ecma-date-props prop-name)
-                    (setq face 'font-lock-builtin-face)))
-               ((string= target-name "Math")
-                (if (string-match js2-ecma-math-funcs prop-name)
-                    (setq face 'font-lock-builtin-face)))))))
-           (prop
-            (if (string-match js2-ecma-global-funcs prop-name)
-                (setq face 'font-lock-builtin-face))))
-        (cond
-         ((and target prop)
-          (cond
-           ((string= target-name "Number")
-            (if (string-match js2-ecma-number-props prop-name)
-                (setq face 'font-lock-constant-face)))
-           ((string= target-name "Math")
-            (if (string-match js2-ecma-math-props prop-name)
-                (setq face 'font-lock-constant-face)))))
-         (prop
-          (if (string-match js2-ecma-object-props prop-name)
-              (setq face 'font-lock-constant-face)))))
-      (when face
-        (js2-set-face (setq pos (+ (js2-node-pos parent) ; absolute
-                                   (js2-node-pos prop))) ; relative
-                      (+ pos (js2-node-len prop))
-                      face)))))
-
-(defun js2-parse-highlight-member-expr-node (node)
-  "Perform syntax highlighting of EcmaScript built-in properties.
-The variable `js2-highlight-level' governs this highighting."
-  (let (face target prop name pos end parent call-p callee)
-    (cond
-     ;; case 1:  simple name, e.g. foo
-     ((js2-name-node-p node)
-      (setq name (js2-name-node-name node))
-      ;; possible for name to be nil in rare cases - saw it when
-      ;; running js2-mode on an elisp buffer.  Might as well try to
-      ;; make it so js2-mode never barfs.
-      (when name
-        (setq face (if (string-match js2-ecma-global-props name)
-                       'font-lock-constant-face))
-        (when face
-          (setq pos (js2-node-pos node)
-                end (+ pos (js2-node-len node)))
-          (js2-set-face pos end face))))
-
-     ;; case 2:  property access or function call
-     ((or (js2-prop-get-node-p node)
-          ;; highlight function call if expr is a prop-get node
-          ;; or a plain name (i.e. unqualified function call)
-          (and (setq call-p (js2-call-node-p node))
-               (setq callee (js2-call-node-target node)) ; separate setq!
-               (or (js2-prop-get-node-p callee)
-                   (js2-name-node-p callee))))
-      (setq parent node
-            node (if call-p callee node))
-      (if (and call-p (js2-name-node-p callee))
-          (setq prop callee)
-        (setq target (js2-prop-get-node-left node)
-              prop (js2-prop-get-node-right node)))
-      (cond
-       ((js2-name-node-p target)
-        (if (js2-name-node-p prop)
-            ;; case 2a:  simple target, simple prop name, e.g. foo.bar
-            (js2-parse-highlight-prop-get parent target prop call-p)
-          ;; case 2b:  simple target, complex name, e.g. foo.x[y]
-          (js2-parse-highlight-prop-get parent target nil call-p)))
-       ((js2-name-node-p prop)
-        ;; case 2c:  complex target, simple name, e.g. x[y].bar
-        (js2-parse-highlight-prop-get parent target prop call-p)))))))
-
-(defun js2-parse-highlight-member-expr-fn-name (expr)
-  "Highlight the `baz' in function foo.bar.baz(args) {...}.
-This is experimental Rhino syntax.  EXPR is the foo.bar.baz member expr.
-We currently only handle the case where the last component is a prop-get
-of a simple name.  Called before EXPR has a parent node."
-  (let (pos
-        (name (and (js2-prop-get-node-p expr)
-                   (js2-prop-get-node-right expr))))
-    (when (js2-name-node-p name)
-      (js2-set-face (setq pos (+ (js2-node-pos expr)  ; parent is absolute
-                                 (js2-node-pos name)))
-                    (+ pos (js2-node-len name))
-                    'font-lock-function-name-face
-                    'record))))
-
-;; source:  http://jsdoc.sourceforge.net/
-;; Note - this syntax is for Google's enhanced jsdoc parser that
-;; allows type specifications, and needs work before entering the wild.
-
-(defconst js2-jsdoc-param-tag-regexp
-  (concat "^\\s-*\\*+\\s-*\\(@"
-          "\\(?:param\\|argument\\)"
-          "\\)"
-          "\\s-*\\({[^}]+}\\)?"         ; optional type
-          "\\s-*\\([a-zA-Z0-9_$]+\\)?"  ; name
-          "\\>")
-  "Matches jsdoc tags with optional type and optional param name.")
-
-(defconst js2-jsdoc-typed-tag-regexp
-  (concat "^\\s-*\\*+\\s-*\\(@\\(?:"
-          (regexp-opt
-           '("requires" "return" "returns" "throw" "throws"))
-          "\\)\\)\\s-*\\({[^}]+}\\)?")
-  "Matches jsdoc tags with optional type.")
-
-(defconst js2-jsdoc-arg-tag-regexp
-  (concat "^\\s-*\\*+\\s-*\\(@\\(?:"
-          (regexp-opt
-           '("base" "extends" "member" "type" "version"))
-          "\\)\\)\\s-+\\([^ \t]+\\)")
-  "Matches jsdoc tags with a single argument.")
-
-(defconst js2-jsdoc-empty-tag-regexp
-  (concat "^\\s-*\\*+\\s-*\\(@\\(?:"
-          (regexp-opt
-           '("addon" "author" "class" "constructor" "deprecated" "exec"
-             "exception" "fileoverview" "final" "ignore" "private"))
-          "\\)\\)\\s-*")
-  "Matches empty jsdoc tags.")
-
-(defconst js2-jsdoc-link-tag-regexp
-  "{\\(@link\\)\\s-+\\([^#}\n]+\\)\\(#.+\\)?}"
-  "Matches a jsdoc link tag.")
-
-(defconst js2-jsdoc-see-tag-regexp
-  "^\\s-*\\*+\\s-*\\(@see\\)\\s-+\\([^#}\n]+\\)\\(#.+\\)?"
-  "Matches a jsdoc @see tag.")
-
-(defconst js2-jsdoc-html-tag-regexp
-  "\\(</?\\)\\([a-zA-Z]+\\)\\s-*\\(/?>\\)"
-  "Matches a simple (no attributes) html start- or end-tag.")
-
-(defsubst js2-jsdoc-highlight-helper ()
-  (js2-set-face (match-beginning 1)
-                (match-end 1)
-                'js2-jsdoc-tag-face)
-  (if (match-beginning 2)
-      (if (save-excursion
-            (goto-char (match-beginning 2))
-            (= (char-after) ?{))
-          (js2-set-face (1+ (match-beginning 2))
-                        (1- (match-end 2))
-                        'js2-jsdoc-type-face)
-        (js2-set-face (match-beginning 2)
-                      (match-end 2)
-                      'js2-jsdoc-value-face)))
-  (if (match-beginning 3)
-      (js2-set-face (match-beginning 3)
-                    (match-end 3)
-                    'js2-jsdoc-value-face)))
-
-(defun js2-highlight-jsdoc (ast)
-  "Highlight doc comment tags."
-  (let ((comments (js2-ast-root-comments ast))
-        beg end)
-    (save-excursion
-      (dolist (node comments)
-        (when (eq (js2-comment-node-format node) 'jsdoc)
-          (setq beg (js2-node-abs-pos node)
-                end (+ beg (js2-node-len node)))
-          (save-restriction
-            (narrow-to-region beg end)
-            (dolist (re (list js2-jsdoc-param-tag-regexp
-                              js2-jsdoc-typed-tag-regexp
-                              js2-jsdoc-arg-tag-regexp
-                              js2-jsdoc-link-tag-regexp
-                              js2-jsdoc-see-tag-regexp
-                              js2-jsdoc-empty-tag-regexp))
-              (goto-char beg)
-              (while (re-search-forward re nil t)
-                (js2-jsdoc-highlight-helper)))
-            ;; simple highlighting for html tags
-            (goto-char beg)
-            (while (re-search-forward js2-jsdoc-html-tag-regexp nil t)
-              (js2-set-face (match-beginning 1)
-                            (match-end 1)
-                            'js2-jsdoc-html-tag-delimiter-face)
-              (js2-set-face (match-beginning 2)
-                            (match-end 2)
-                            'js2-jsdoc-html-tag-name-face)
-              (js2-set-face (match-beginning 3)
-                            (match-end 3)
-                            'js2-jsdoc-html-tag-delimiter-face))))))))
-
-(defun js2-highlight-assign-targets (node left right)
-  "Highlight function properties and external variables."
-  (let (leftpos end name)
-    ;; highlight vars and props assigned function values
-    (when (js2-function-node-p right)
-      (cond
-       ;; var foo = function() {...}
-       ((js2-name-node-p left)
-        (setq name left))
-
-       ;; foo.bar.baz = function() {...}
-       ((and (js2-prop-get-node-p left)
-             (js2-name-node-p (js2-prop-get-node-right left)))
-        (setq name (js2-prop-get-node-right left))))
-
-      (when name
-        (js2-set-face (setq leftpos (js2-node-abs-pos name))
-                      (+ leftpos (js2-node-len name))
-                      'font-lock-function-name-face
-                      'record)))
-
-    ;; save variable assignments so we can check for undeclared later
-    ;; (can't do it here since var decls can come at end of script)
-    (when (and js2-highlight-external-variables
-               (setq name (js2-member-expr-leftmost-name left)))
-      (push (list name js2-current-scope
-                  (setq leftpos (js2-node-abs-pos name))
-                  (setq end (+ leftpos (js2-node-len name))))
-            js2-recorded-assignments))))
-
-(defun js2-highlight-undeclared-vars ()
-  "After entire parse is finished, look for undeclared variable assignments.
-Have to wait until entire buffer is parsed, since JavaScript permits var
-decls to occur after they're used.
-
-We currently use a simple heuristic to rule out complaining about built-ins:
-if the name is capitalized we don't highlight it.  This could be improved a
-bit by declaring all the Ecma global object, constructor and function names
-in a hashtable, but we'd still wind up complaining about all the DHTML
-builtins, the Mozilla builtins, etc."
-  (let (name first-char)
-    (dolist (entry js2-recorded-assignments)
-      (destructuring-bind (name-node scope pos end) entry
-        (setq name (js2-name-node-name name-node)
-              first-char (aref name 0))
-        (unless (or (and (>= first-char ?A) (<= first-char ?Z))
-                    (js2-get-defining-scope scope name))
-          (js2-set-face pos end 'js2-external-variable-face 'record)
-          (js2-record-text-property pos end 'help-echo "Undeclared variable")
-          (js2-record-text-property pos end 'point-entered #'js2-echo-help))))
-    (setq js2-recorded-assignments nil)))
-
-(provide 'js2-highlight)
-
-;;; js2-highlight.el ends here
-;;; js2-browse.el --- browsing/hierarchy support for js2-mode
-
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Keywords:  javascript languages
-
-;; Commentary:
-;;
-;; We currently only support imenu, but eventually should support speedbar and
-;; possibly other browsing mechanisms.
-;;
-;; The basic strategy is to identify function assignment targets of the form
-;; `foo.bar.baz', convert them to (list foo bar baz <position>), and push the
-;; list into `js2-imenu-recorder'.  The lists are merged into a trie-like tree
-;; for imenu after parsing is finished.
-;;
-;; A `foo.bar.baz' assignment target may be expressed in many ways in
-;; JavaScript, and the general problem is undecidable.  However, several forms
-;; are readily recognizable at parse-time; the forms we attempt to recognize
-;; include:
-;;
-;;  function foo()  -- function declaration
-;;  foo = function()  -- function expression assigned to variable
-;;  foo.bar.baz = function()  -- function expr assigned to nested property-get
-;;  foo = {bar: function()}  -- fun prop in object literal assigned to var
-;;  foo = {bar: {baz: function()}} -- inside nested object literal
-;;  foo.bar = {baz: function()}} -- obj lit assigned to nested prop get
-;;  a.b = {c: {d: function()}} -- nested obj lit assigned to nested prop get
-;;  foo = {get bar() {...}}  -- getter/setter in obj literal
-;;  function foo() {function bar() {...}}  -- nested function
-;;  foo['a'] = function()  -- fun expr assigned to deterministic element-get
-;;
-;; This list boils down to a few forms that can be combined recursively.
-;; Top-level named function declarations include both the left-hand (name)
-;; and the right-hand (function value) expressions needed to produce an imenu
-;; entry.  The other "right-hand" forms we need to look for are:
-;;  - functions declared as props/getters/setters in object literals
-;;  - nested named function declarations
-;; The "left-hand" expressions that functions can be assigned to include:
-;;  - local/global variables
-;;  - nested property-get expressions like a.b.c.d
-;;  - element gets like foo[10] or foo['bar'] where the index
-;;    expression can be trivially converted to a property name.  They
-;;    effectively then become property gets.
-;;
-;; All the different definition types are canonicalized into the form
-;; foo.bar.baz = position-of-function-keyword
-;;
-;; We need to build a trie-like structure for imenu.  As an example,
-;; consider the following JavaScript code:
-;;
-;; a = function() {...}  // function at position 5
-;; b = function() {...}  // function at position 25
-;; foo = function() {...} // function at position 100
-;; foo.bar = function() {...} // function at position 200
-;; foo.bar.baz = function() {...} // function at position 300
-;; foo.bar.zab = function() {...} // function at position 400
-;;
-;; During parsing we accumulate an entry for each definition in
-;; the variable `js2-imenu-recorder', like so:
-;;
-;; '((a 5)
-;;   (b 25)
-;;   (foo 100)
-;;   (foo bar 200)
-;;   (foo bar baz 300)
-;;   (foo bar zab 400))
-;;
-;; After parsing these entries are merged into this alist-trie:
-;;
-;; '((a . 1)
-;;   (b . 2)
-;;   (foo (<definition> . 3)
-;;        (bar (<definition> . 6)
-;;             (baz . 100)
-;;             (zab . 200))))
-;;
-;; Note the wacky need for a <definition> name.  The token can be anything
-;; that isn't a valid JavaScript identifier, because you might make foo
-;; a function and then start setting properties on it that are also functions.
-
-;;; Code:
-
-
-(defsubst js2-prop-node-name (node)
-  "Return the name of a node that may be a property-get/property-name.
-If NODE is not a valid name-node, string-node or integral number-node,
-returns nil.  Otherwise returns the string name/value of the node."
-  (cond
-   ((js2-name-node-p node)
-    (js2-name-node-name node))
-   ((js2-string-node-p node)
-    (js2-string-node-value node))
-   ((and (js2-number-node-p node)
-         (string-match "^[0-9]+$" (js2-number-node-value node)))
-    (js2-number-node-value node))
-   ((js2-this-node-p node)
-    "this")))
-
-(defsubst js2-node-qname-component (node)
-  "Test function:  return the name of this node, if it contributes to a qname.
-Returns nil if the node doesn't contribute."
-  (copy-sequence
-   (or (js2-prop-node-name node)
-       (if (and (js2-function-node-p node)
-                (js2-function-node-name node))
-           (js2-name-node-name (js2-function-node-name node))))))
-
-(defsubst js2-record-function-qname (fn-node qname)
-  "Associate FN-NODE with its QNAME for later lookup.
-This is used in postprocessing the chain list.  When we find a chain
-whose first element is a js2-THIS keyword node, we look up the parent
-function and see (using this map) whether it is the tail of a chain.
-If so, we replace the this-node with a copy of the parent's qname."
-  (unless js2-imenu-function-map
-    (setq js2-imenu-function-map (make-hash-table :test 'eq)))
-  (puthash fn-node qname js2-imenu-function-map))
-
-(defun js2-record-imenu-functions (node &optional var)
-  "Record function definitions for imenu.
-NODE is a function node or an object literal.
-VAR, if non-nil, is the expression that NODE is being assigned to."
-  (when js2-parse-ide-mode
-    (let ((fun-p (js2-function-node-p node))
-          qname left fname-node pos)
-      (cond
-       ;; non-anonymous function declaration?
-       ((and fun-p
-             (not var)
-             (setq fname-node (js2-function-node-name node)))
-        (push (setq qname (list fname-node (js2-node-pos node)))
-              js2-imenu-recorder)
-        (js2-record-function-qname node qname))
-
-       ;; for remaining forms, compute left-side tree branch first
-       ((and var (setq qname (js2-compute-nested-prop-get var)))
-        (cond
-         ;; foo.bar.baz = function
-         (fun-p
-          (push (nconc qname (list (js2-node-pos node)))
-                js2-imenu-recorder)
-          (js2-record-function-qname node qname))
-         ;; foo.bar.baz = object-literal
-         ;; look for nested functions:  {a: {b: function() {...} }}
-         ((js2-object-node-p node)
-          (js2-record-object-literal node qname))))))))
-
-(defun js2-compute-nested-prop-get (node)
-  "If NODE is of form foo.bar.baz, return component nodes as a list.
-Otherwise returns nil.  Element-gets can be treated as property-gets
-if the index expression is a name, a string, or a positive integer."
-  (let (left right head)
-    (cond
-     ((or (js2-name-node-p node)
-          (js2-this-node-p node))
-      (list node))
-     ;; foo.bar.baz is parenthesized as (foo.bar).baz => right operand is a leaf
-     ((js2-prop-get-node-p node)  ; includes elem-get nodes
-      (setq left (js2-prop-get-node-left node)
-            right (js2-prop-get-node-right node))
-      (if (and (or (js2-prop-get-node-p left)     ; left == foo.bar
-                   (js2-name-node-p left)
-                   (js2-this-node-p left))        ; or left == foo
-               (or (js2-name-node-p right)        ; .bar
-                   (js2-string-node-p right)      ; ['bar']
-                   (and (js2-number-node-p right) ; [10]
-                        (string-match "^[0-9]+$"
-                                      (js2-number-node-value right)))))
-          (if (setq head (js2-compute-nested-prop-get left))
-              (nconc head (list right))))))))
-
-(defun js2-record-object-literal (node qname)
-  "Recursively process an object literal looking for functions.
-NODE is an object literal that is the right-hand child of an assignment
-expression.  QNAME is a list of nodes representing the assignment target,
-e.g. for foo.bar.baz = {...}, QNAME is (foo-node bar-node baz-node).
-We do a depth-first traversal of NODE.  Any functions we find are prefixed
-with QNAME plus the property name of the function and appended to the
-variable `js2-imenu-recorder'."
-  ;; Elements are relative to parent position, which is still absolute,
-  ;; since the parser passes the assignment target and value expressions
-  ;; to us before they are added as children of the assignment node.
-  (let ((pos (js2-node-pos node))
-        left right)
-    (dolist (e (js2-object-node-elems node))  ; e is a `js2-object-prop-node'
-      (setq left (js2-infix-node-left e))
-      (cond
-       ;; foo: function() {...}
-       ((js2-function-node-p (setq right (js2-infix-node-right e)))
-        (when (js2-prop-node-name left)
-          ;; As a policy decision, we record the position of the property,
-          ;; not the position of the `function' keyword, since the property
-          ;; is effectively the name of the function.
-          (push (append qname (list left) (list (+ pos (js2-node-pos e))))
-                js2-imenu-recorder)
-          (js2-record-function-qname right qname)))
-       ;; foo: {object-literal} -- add foo to qname and recurse
-       ((js2-object-node-p right)
-        (js2-record-object-literal right
-                                   (append qname (list (js2-infix-node-left e)))))))))
-
-(defsubst js2-node-top-level-decl-p (node)
-  "Return t if NODE's name is defined in the top-level scope.
-Also returns t if NODE's name is not defined in any scope, since it implies
-that it's an external variable, which must also be in the top-level scope."
-  (let* ((name (js2-prop-node-name node))
-         (this-scope (js2-node-get-enclosing-scope node))
-         defining-scope)
-    (cond
-     ((js2-this-node-p node)
-      nil)
-     ((null this-scope)
-      t)
-     ((setq defining-scope (js2-get-defining-scope this-scope name))
-      (js2-ast-root-p defining-scope))
-     (t t))))
-
-(defun js2-browse-postprocess-chains (chains)
-  "Modify function-declaration name chains after parsing finishes.
-Some of the information is only available after the parse tree is complete.
-For instance, following a 'this' reference requires a parent function node."
-  (let (result head fn parent-chain p elem)
-    (dolist (chain chains)
-      ;; examine the head of each node to get its defining scope
-      (setq head (car chain))
-      (cond
-       ;; if top-level/external, keep as-is
-       ((js2-node-top-level-decl-p head)
-        (push chain result))
-       ;; check for a this-reference
-       ((eq (js2-node-type head) js2-THIS)
-        (setq fn (js2-node-parent-script-or-fn head))
-        ;; if there is no parent function, or if the parent function
-        ;; is nested, discard the head node and keep the rest of the chain.
-        (if (or (null fn) (js2-nested-function-p fn))
-            (push (cdr chain) result)
-          ;; else look up parent in function-map.  If not found, discard chain.
-          (when (setq parent-chain (and js2-imenu-function-map
-                                        (gethash fn js2-imenu-function-map)))
-            ;; else discard head node and prefix parent fn qname, which is
-            ;; the parent-chain sans tail, to this chain.
-            (push (append (butlast parent-chain) (cdr chain)) result))))))
-    ;; finally replace each node in each chain with its name.
-    (dolist (chain result)
-      (setq p chain)
-      (while p
-        (if (js2-node-p (setq elem (car p)))
-            (setcar p (js2-node-qname-component elem)))
-        (setq p (cdr p))))
-    result))
-
-;; Merge name chains into a trie-like tree structure of nested lists.
-;; To simplify construction of the trie, we first build it out using the rule
-;; that the trie consists of lists of pairs.  Each pair is a 2-element array:
-;; [key, num-or-list].  The second element can be a number; if so, this key
-;; is a leaf-node with only one value.  (I.e. there is only one declaration
-;; associated with the key at this level.)  Otherwise the second element is
-;; a list of pairs, with the rule applied recursively.  This symmetry permits
-;; a simple recursive formulation.
-;;
-;; js2-mode is building the data structure for imenu.  The imenu documentation
-;; claims that it's the structure above, but in practice it wants the children
-;; at the same list level as the key for that level, which is how I've drawn
-;; the "Expected final result" above.  We'll postprocess the trie to remove the
-;; list wrapper around the children at each level.
-;;
-;; A completed nested imenu-alist entry looks like this:
-;;       '(("foo"
-;;          ("<definition>" . 7)
-;;          ("bar"
-;;           ("a" . 40)
-;;           ("b" . 60))))
-;;
-;; In particular, the documentation for `imenu--index-alist' says that
-;; a nested sub-alist element looks like (INDEX-NAME SUB-ALIST).
-;; The sub-alist entries immediately follow INDEX-NAME, the head of the list.
-
-(defsubst js2-treeify (lst)
-  "Convert (a b c d) to (a ((b ((c d)))))"
-  (if (null (cddr lst))  ; list length <= 2
-      lst
-    (list (car lst) (list (js2-treeify (cdr lst))))))
-
-(defun js2-build-alist-trie (chains trie)
-  "Merge declaration name chains into a trie-like alist structure for imenu.
-CHAINS is the qname chain list produced during parsing. TRIE is a
-list of elements built up so far."
-  (let (head tail pos branch kids)
-    (dolist (chain chains)
-      (setq head (car chain)
-            tail (cdr chain)
-            pos (if (numberp (car tail)) (car tail))
-            branch (js2-find-if (lambda (n)
-                                  (string= (car n) head))
-                                trie)
-            kids (second branch))
-      (cond
-       ;; case 1:  this key isn't in the trie yet
-       ((null branch)
-        (if trie
-            (setcdr (last trie) (list (js2-treeify chain)))
-          (setq trie (list (js2-treeify chain)))))
-
-       ;; case 2:  key is present with a single number entry:  replace w/ list
-       ;;  ("a1" 10)  +  ("a1" 20) => ("a1" (("<definition>" 10)
-       ;;                                    ("<definition>" 20)))
-       ((numberp kids)
-        (setcar (cdr branch)
-                (list (list "<definition-1>" kids)
-                      (if pos
-                          (list "<definition-2>" pos)
-                        (js2-treeify tail)))))
-
-       ;; case 3:  key is there (with kids), and we're a number entry
-       (pos
-        (setcdr (last kids)
-                (list
-                 (list (format "<definition-%d>"
-                               (1+ (loop for kid in kids
-                                         count (eq ?< (aref (car kid) 0)))))
-                       pos))))
-
-       ;; case 4:  key is there with kids, need to merge in our chain
-       (t
-        (js2-build-alist-trie (list tail) kids))))
-    trie))
-
-(defun js2-flatten-trie (trie)
-  "Convert TRIE to imenu-format.
-Recurses through nodes, and for each one whose second element is a list,
-appends the list's flattened elements to the current element.  Also
-changes the tails into conses.  For instance, this pre-flattened trie
-
-'(a ((b 20)
-     (c ((d 30)
-         (e 40)))))
-
-becomes
-
-'(a (b . 20)
-    (c (d . 30)
-       (e . 40)))
-
-Note that the root of the trie has no key, just a list of chains.
-This is also true for the value of any key with multiple children,
-e.g. key 'c' in the example above."
-  (cond
-   ((listp (car trie))
-    (mapcar #'js2-flatten-trie trie))
-   (t
-    (if (numberp (second trie))
-        (cons (car trie) (second trie))
-      ;; else pop list and append its kids
-      (apply #'append (list (car trie)) (js2-flatten-trie (cdr trie)))))))
-
-(defun js2-build-imenu-index ()
-  "Turn `js2-imenu-recorder' into an imenu data structure."
-  (unless (eq js2-imenu-recorder 'empty)
-    (let* ((chains (js2-browse-postprocess-chains js2-imenu-recorder))
-           (result (js2-build-alist-trie chains nil)))
-      (js2-flatten-trie result))))
-
-(defun js2-test-print-chains (chains)
-  "Print a list of qname chains.
-Each element of CHAINS is a list of the form (NODE [NODE *] pos);
-i.e. one or more nodes, and an integer position as the list tail."
-  (mapconcat (lambda (chain)
-               (concat "("
-                       (mapconcat (lambda (elem)
-                                    (if (js2-node-p elem)
-                                        (or (js2-node-qname-component elem)
-                                            "nil")
-                                      (number-to-string elem)))
-                                  chain
-                                  " ")
-                       ")"))
-             chains
-             "\n"))
-
-
-(provide 'js2-browse)
-
-;;; js2-browse.el ends here
-;;; js2-parse.el --- JavaScript parser
-
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Keywords:  javascript languages
-
-;; Commentary:
-
-;; This is based on Rhino's parser and tries to follow its code
-;; structure as closely as practical, so that changes to the Rhino
-;; parser can easily be propagated into this code.  However, Rhino
-;; does not currently generate a usable AST representation, at least
-;; from an IDE perspective, so we build our own more suitable AST.
-
-;; The AST node structures are defined in `js2-ast.el'.
-;; Every parser function that creates and returns an AST node has
-;; the following responsibilities:
-
-;;   1) set the node start to the absolute buffer start position
-;;   2) set the node length to include any closing chars (RC, SEMI)
-;;   3) fix up any child-node starts to be relative to this node
-;;   4) set any field positions (e.g. keywords) relative to this node
-;;   5) report any child nodes with `js2-node-add-children'
-;;      (note that this call fixes up start positions by default)
-
-;; The resulting AST has all node start positions relative to the
-;; parent nodes; only the root has an absolute start position.
-
-;; Note: fontification is done inline while parsing.  It used to be
-;; done in a second pass over the AST, but doing it inline is about
-;; twice as fast.  Most of the fontification happens when tokens are
-;; scanned, and the parser has a few spots that perform extra
-;; fontification.  In addition to speed, a second benefit of inline
-;; parsing is that if a long parse is interrupted, everything parsed
-;; so far is still fontified.
-
-;; The editing mode that uses this parser, `js2-mode', directs the
-;; parser to check periodically for user input.  If user input
-;; arrives, the parse is abandoned, except for the highlighting that
-;; has occurred so far, and a re-parse is rescheduled for when Emacs
-;; becomes idle again.  This works pretty well, but could be better.
-;; In particular, when the user input has not resulted in changes to
-;; the buffer (for instance, navigation input), the parse tree built
-;; so far should not be discarded, and the parse should continue where
-;; it left off.  It will be some work to create what amounts to a
-;; continuation, but it should not be unreasonably difficult.
-
-;; TODO:
-;; - make non-editing input restart parse at previous continuation
-;; - in Eclipse, sibling nodes never overlap start/end ranges
-;;   - for getters, prop name and function nodes overlap
-;;   - should write a debug tree visitor to look for overlaps
-;; - mark array and object literals as "destructuring" (node prop?)
-;;   so we can syntax-highlight them properly.
-;; - figure out a way not to store value in string/name nodes
-;;   - needs a solution for synthetic nodes
-
-;;; Code
-
-(eval-and-compile
-  (require 'cl))  ; for delete-if
-
-
-(defconst js2-version "1.7.0"
-  "Version of JavaScript supported, plus minor js2 version.")
-
-(defmacro js2-record-face (face)
-  "Record a style run of FACE for the current token."
-  `(js2-set-face js2-token-beg js2-token-end ,face 'record))
-
-(defsubst js2-node-end (n)
-  "Computes the absolute end of node N.
-Use with caution!  Assumes `js2-node-pos' is -absolute-, which
-is only true until the node is added to its parent; i.e., while parsing."
-  (+ (js2-node-pos n)
-     (js2-node-len n)))
-
-(defsubst js2-record-comment ()
-  (push (make-js2-comment-node :len (- js2-token-end js2-token-beg)
-                               :format js2-ts-comment-type)
-        js2-scanned-comments)
-  (when js2-parse-ide-mode
-    (js2-record-face 'font-lock-comment-face)
-    (when (memq js2-ts-comment-type '(html preprocessor))
-      ;; Tell cc-engine the bounds of the comment.
-      (put-text-property js2-token-beg (1- js2-token-end) 'c-in-sws t))))
-
-;; This function is called depressingly often, so it should be fast.
-;; Most of the time it's looking at the same token it peeked before.
-(defsubst js2-peek-token ()
-  "Returns the next token without consuming it.
-If previous token was consumed, calls scanner to get new token.
-If previous token was -not- consumed, returns it (idempotent).
-
-This function will not return a newline (js2-EOL) - instead, it
-gobbles newlines until it finds a non-newline token, and flags
-that token as appearing just after a newline.
-
-This function will also not return a js2-COMMENT.  Instead, it
-records comments found in `js2-scanned-comments'.  If the token
-returned by this function immediately follows a jsdoc comment,
-the token is flagged as such.
-
-Note that this function always returned the un-flagged token!
-The flags, if any, are saved in `js2-current-flagged-token'."
-  (if (/= js2-current-flagged-token js2-EOF) ; last token not consumed
-      js2-current-token  ; most common case - return already-peeked token
-    (let ((tt (js2-get-token))          ; call scanner
-          saw-eol
-          face)
-      ;; process comments and whitespace
-      (while (or (= tt js2-EOL)
-                 (= tt js2-COMMENT))
-        (if (= tt js2-EOL)
-            (setq saw-eol t)
-          (setq saw-eol nil)
-          (if js2-record-comments
-              (js2-record-comment)))
-        (setq tt (js2-get-token)))  ; call scanner
-
-      (setq js2-current-token tt
-            js2-current-flagged-token (if saw-eol
-                                          (logior tt js2-ti-after-eol)
-                                        tt))
-      ;; perform lexical fontification as soon as token is scanned
-      (when js2-parse-ide-mode
-        (cond
-         ((minusp tt)
-          (js2-record-face 'js2-error-face))
-         ((setq face (aref js2-kwd-tokens tt))
-          (js2-record-face face))
-         ((and (= tt js2-NAME)
-               (equal js2-ts-string "undefined"))
-          (js2-record-face 'font-lock-constant-face))))
-      tt)))  ; return unflagged token
-
-(defsubst js2-peek-flagged-token ()
-  "Returns the current token along with any flags set for it."
-  (js2-peek-token)
-  js2-current-flagged-token)
-
-(defsubst js2-consume-token ()
-  (setq js2-current-flagged-token js2-EOF))
-
-(defsubst js2-next-token ()
-  (prog1
-      (js2-peek-token)
-    (js2-consume-token)))
-
-(defsubst js2-next-flagged-token ()
-  (js2-peek-token)
-  (prog1 js2-current-flagged-token
-    (js2-consume-token)))
-
-(defsubst js2-match-token (match)
-  "Consume and return t if next token matches MATCH, a bytecode.
-Returns nil and consumes nothing if MATCH is not the next token."
-  (if (/= (js2-peek-token) match)
-      nil
-    (js2-consume-token)
-    t))
-
-(defsubst js2-valid-prop-name-token (tt)
-  (or (= tt js2-NAME)
-      (and js2-allow-keywords-as-property-names
-           (plusp tt)
-           (aref js2-kwd-tokens tt))))
-
-(defsubst js2-match-prop-name ()
-  "Consume token and return t if next token is a valid property name.
-It's valid if it's a js2-NAME, or `js2-allow-keywords-as-property-names'
-is non-nil and it's a keyword token."
-  (if (js2-valid-prop-name-token (js2-peek-token))
-      (progn
-        (js2-consume-token)
-        t)
-    nil))
-
-(defsubst js2-must-match-prop-name (msg-id &optional pos len)
-  (if (js2-match-prop-name)
-      t
-    (js2-report-error msg-id nil pos len)
-    nil))
-
-(defsubst js2-peek-token-or-eol ()
-  "Return js2-EOL if the current token immediately follows a newline.
-Else returns the current token.  Used in situations where we don't
-consider certain token types valid if they are preceded by a newline.
-One example is the postfix ++ or -- operator, which has to be on the
-same line as its operand."
-  (let ((tt (js2-peek-token)))
-    ;; Check for last peeked token flags
-    (if (js2-flag-set-p js2-current-flagged-token js2-ti-after-eol)
-        js2-EOL
-      tt)))
-
-(defsubst js2-set-check-for-label ()
-  (assert (= (logand js2-current-flagged-token js2-clear-ti-mask) js2-NAME))
-  (js2-set-flag js2-current-flagged-token js2-ti-check-label))
-
-(defsubst js2-must-match (token msg-id &optional pos len)
-  "Match next token to token code TOKEN, or record a syntax error.
-MSG-ID is the error message to report if the match fails.
-Returns t on match, nil if no match."
-  (if (js2-match-token token)
-      t
-    (js2-report-error msg-id nil pos len)
-    nil))
-
-(defsubst js2-inside-function ()
-  (plusp js2-nesting-of-function))
-
-(defsubst js2-set-requires-activation ()
-  (if (js2-function-node-p js2-current-script-or-fn)
-      (setf (js2-function-node-needs-activation js2-current-script-or-fn) t)))
-
-(defsubst js2-check-activation-name (name token)
-  (when (js2-inside-function)
-    ;; skip language-version 1.2 check from Rhino
-    (if (or (string= "arguments" name)
-            (and js2-compiler-activation-names  ; only used in codegen
-                 (gethash name js2-compiler-activation-names)))
-        (js2-set-requires-activation))))
-
-(defsubst js2-set-is-generator ()
-  (if (js2-function-node-p js2-current-script-or-fn)
-      (setf (js2-function-node-is-generator js2-current-script-or-fn) t)))
-
-(defsubst js2-must-have-xml ()
-  (unless js2-compiler-xml-available
-    (js2-report-error "msg.XML.not.available")))
-
-(defsubst js2-push-scope (scope)
-  "Push SCOPE, a `js2-scope', onto the lexical scope chain."
-  (assert (js2-scope-p scope))
-  (assert (null (js2-scope-parent-scope scope)))
-  (assert (neq js2-current-scope scope))
-  (setf (js2-scope-parent-scope scope) js2-current-scope
-        js2-current-scope scope))
-
-(defsubst js2-pop-scope ()
-  (setq js2-current-scope
-        (js2-scope-parent-scope js2-current-scope)))
-
-(defsubst js2-enter-loop (loop-node)
-  (push loop-node js2-loop-set)
-  (push loop-node js2-loop-and-switch-set)
-  (js2-push-scope loop-node)
-  ;; Tell the current labeled statement (if any) its statement,
-  ;; and set the jump target of the first label to the loop.
-  ;; These are used in `js2-parse-continue' to verify that the
-  ;; continue target is an actual labeled loop.  (And for codegen.)
-  (when js2-labeled-stmt
-    (setf (js2-labeled-stmt-node-stmt js2-labeled-stmt) loop-node
-          (js2-label-node-loop (car (js2-labeled-stmt-node-labels
-                                     js2-labeled-stmt))) loop-node)))
-
-(defsubst js2-exit-loop ()
-  (pop js2-loop-set)
-  (pop js2-loop-and-switch-set)
-  (js2-pop-scope))
-
-(defsubst js2-enter-switch (switch-node)
-  (push switch-node js2-loop-and-switch-set))
-
-(defsubst js2-exit-switch ()
-  (pop js2-loop-and-switch-set))
-
-(defun js2-parse (&optional buf cb)
-  "Tells the js2 parser to parse a region of JavaScript.
-
-BUF is a buffer or buffer name containing the code to parse.
-Call `narrow-to-region' first to parse only part of the buffer.
-
-The returned AST root node is given some additional properties:
-  `node-count' - total number of nodes in the AST
-  `buffer' - BUF.  The buffer it refers to may change or be killed,
-             so the value is not necessarily reliable.
-
-An optional callback CB can be specified to report parsing
-progress.  If `(functionp CB)' returns t, it will be called with
-the current line number once before parsing begins, then again
-each time the lexer reaches a new line number.
-
-CB can also be a list of the form `(symbol cb ...)' to specify
-multiple callbacks with different criteria.  Each symbol is a
-criterion keyword, and the following element is the callback to
-call
-
-  :line  - called whenever the line number changes
-  :token - called for each new token consumed
-
-The list of criteria could be extended to include entering or
-leaving a statement, an expression, or a function definition."
-  (if (and cb (not (functionp cb)))
-      (error "criteria callbacks not yet implemented"))
-  (let ((inhibit-point-motion-hooks t)
-        (js2-compiler-xml-available (>= js2-language-version 160))
-        ;; 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))
-        (case-fold-search nil)
-        ast)
-    (or buf (setq buf (current-buffer)))
-    (save-excursion
-      (set-buffer buf)
-      (setq js2-scanned-comments nil
-            js2-parsed-errors nil
-            js2-parsed-warnings nil
-            js2-imenu-recorder nil
-            js2-imenu-function-map nil
-            js2-label-set nil)
-      (js2-init-scanner)
-      (setq ast (js2-with-unmodifying-text-property-changes
-                  (js2-do-parse)))
-      (unless js2-ts-hit-eof
-        (js2-report-error "msg.got.syntax.errors" (length js2-parsed-errors)))
-      (setf (js2-ast-root-errors ast) js2-parsed-errors
-            (js2-ast-root-warnings ast) js2-parsed-warnings)
-      ;; if we didn't find any declarations, put a dummy in this list so we
-      ;; don't end up re-parsing the buffer in `js2-mode-create-imenu-index'
-      (unless js2-imenu-recorder
-        (setq js2-imenu-recorder 'empty))
-      (run-hooks 'js2-parse-finished-hook)
-      ast)))
-
-;; Corresponds to Rhino's Parser.parse() method.
-(defun js2-do-parse ()
-  "Parse current buffer starting from current point.
-Scanner should be initialized."
-  (let ((pos js2-ts-cursor)
-        (end js2-ts-cursor)  ; in case file is empty
-        root n tt)
-    ;; initialize buffer-local parsing vars
-    (setf root (make-js2-ast-root :buffer (buffer-name) :pos pos)
-          js2-current-script-or-fn root
-          js2-current-scope root
-          js2-current-flagged-token js2-EOF
-          js2-nesting-of-function 0
-          js2-labeled-stmt nil
-          js2-recorded-assignments nil)  ; for js2-highlight
-
-    (while (/= (setq tt (js2-peek-token)) js2-EOF)
-      (if (= tt js2-FUNCTION)
-          (progn
-            (js2-consume-token)
-            (setq n (js2-parse-function (if js2-called-by-compile-function
-                                            'FUNCTION_EXPRESSION
-                                          'FUNCTION_STATEMENT)))
-            (js2-record-imenu-functions n))
-        ;; not a function - parse a statement
-        (setq n (js2-parse-statement)))
-      ;; add function or statement to script
-      (setq end (js2-node-end n))
-      (js2-block-node-push root n))
-
-    ;; add comments to root in lexical order
-    (when js2-scanned-comments
-      ;; if we find a comment beyond end of normal kids, use its end
-      (setq end (max end (js2-node-end (first js2-scanned-comments))))
-      (dolist (comment js2-scanned-comments)
-        (push comment (js2-ast-root-comments root))
-        (js2-node-add-children root comment)))
-
-    (setf (js2-node-len root) (- end pos))
-    (js2-highlight-undeclared-vars)
-    root))
-
-(defun js2-function-parser ()
-  (js2-consume-token)
-  (js2-parse-function 'FUNCTION_EXPRESSION_STATEMENT))
-
-(defun js2-parse-function-body (fn-node)
-  (js2-must-match js2-LC "msg.no.brace.body")
-  (let ((pos js2-token-beg)         ; LC position
-        (pn (make-js2-block-node))  ; starts at LC position
-        tt
-        end)
-    (incf js2-nesting-of-function)
-    (unwind-protect
-        (while (not (or (= (setq tt (js2-peek-token)) js2-ERROR)
-                        (= tt js2-EOF)
-                        (= tt js2-RC)))
-          (js2-block-node-push pn (if (/= tt js2-FUNCTION)
-                                      (js2-parse-statement)
-                                    (js2-consume-token)
-                                    (js2-parse-function 'FUNCTION_STATEMENT))))
-      (decf js2-nesting-of-function))
-    (setq end js2-token-end)  ; assume no curly and leave at current token
-    (if (js2-must-match js2-RC "msg.no.brace.after.body" pos)
-        (setq end js2-token-end))
-    (setf (js2-node-pos pn) pos
-          (js2-node-len pn) (- end pos))
-    (setf (js2-function-node-body fn-node) pn)
-    (js2-node-add-children fn-node pn)
-    pn))
-
-(defun js2-parse-function-params (fn-node pos)
-  (if (js2-match-token js2-RP)
-      (setf (js2-function-node-rp fn-node) (- js2-token-beg pos))
-    (let (params len param)
-      (loop for tt = (js2-peek-token)
-            do
-            (cond
-             ;; destructuring param
-             ((or (= tt js2-LB) (= tt js2-LC))
-              (push (js2-parse-primary-expr) params))
-             ;; simple name
-             (t
-              (js2-must-match js2-NAME "msg.no.parm")
-              (js2-record-face 'js2-function-param-face)
-              (setq param (js2-create-name-node))
-              (js2-define-symbol js2-LP js2-ts-string param)
-              (push param params)))
-            while
-            (js2-match-token js2-COMMA))
-      (if (js2-must-match js2-RP "msg.no.paren.after.parms")
-          (setf (js2-function-node-rp fn-node) (- js2-token-beg pos)))
-      (dolist (p params)
-        (js2-node-add-children fn-node p)
-        (push p (js2-function-node-params fn-node))))))
-
-(defsubst js2-check-inconsistent-return-warning (fn-node name)
-  "Possibly show inconsistent-return warning.
-Last token scanned is the close-curly for the function body."
-  (when (and js2-mode-show-strict-warnings
-             js2-strict-inconsistent-return-warning
-             (not (js2-has-consistent-return-usage
-                   (js2-function-node-body fn-node))))
-    ;; Have it extend from close-curly to bol or beginning of block.
-    (let ((pos (save-excursion
-                 (goto-char js2-token-end)
-                 (max (js2-node-abs-pos (js2-function-node-body fn-node))
-                      (point-at-bol))))
-          (end js2-token-end))
-      (if (plusp (js2-name-node-length name))
-          (js2-add-strict-warning "msg.no.return.value"
-                                  (js2-name-node-name name) pos end)
-        (js2-add-strict-warning "msg.anon.no.return.value" nil pos end)))))
-
-(defun js2-parse-function (function-type)
-  "Function parser.  FUNCTION-TYPE is a symbol."
-  (let ((pos js2-token-beg)  ; start of 'function' keyword
-        name
-        name-beg
-        name-end
-        fn-node
-        lp
-        (synthetic-type function-type)
-        member-expr-node)
-
-    ;; parse function name, expression, or non-name (anonymous)
-    (cond
-     ;; function foo(...)
-     ((js2-match-token js2-NAME)
-      (setq name (js2-create-name-node t)
-            name-beg js2-token-beg
-            name-end js2-token-end)
-      (unless (js2-match-token js2-LP)
-        (when js2-allow-member-expr-as-function-name
-          ;; function foo.bar(...)
-          (setq member-expr-node name
-                name nil
-                member-expr-node (js2-parse-member-expr-tail
-                                  nil member-expr-node)))
-        (js2-must-match js2-LP "msg.no.paren.parms")))
-
-     ((js2-match-token js2-LP)
-      nil)  ; anonymous function:  leave name as null
-
-     (t
-      ;; function random-member-expr(...)
-      (when js2-allow-member-expr-as-function-name
-        ;; Note that memberExpr can not start with '(' like
-        ;; in function (1+2).toString(), because 'function (' already
-        ;; processed as anonymous function
-        (setq member-expr-node (js2-parse-member-expr)))
-      (js2-must-match js2-LP "msg.no.paren.parms")))
-
-    (if (= js2-current-token js2-LP)  ; eventually matched LP?
-        (setq lp js2-token-beg))
-
-    (if member-expr-node
-        (progn
-          (setq synthetic-type 'FUNCTION_EXPRESSION)
-          (js2-parse-highlight-member-expr-fn-name member-expr-node))
-      (if name
-          (js2-set-face name-beg name-end
-                        'font-lock-function-name-face 'record)))
-
-    (if (and (neq synthetic-type 'FUNCTION_EXPRESSION)
-             (plusp (js2-name-node-length name)))
-        ;; Function statements define a symbol in the enclosing scope
-        (js2-define-symbol js2-FUNCTION (js2-name-node-name name) fn-node))
-
-    (setf fn-node (make-js2-function-node :pos pos
-                                          :name name
-                                          :form function-type
-                                          :lp (if lp (- lp pos))))
-
-    (if (or (js2-inside-function) (plusp js2-nesting-of-with))
-        ;; 1. Nested functions are not affected by the dynamic scope flag
-        ;;    as dynamic scope is already a parent of their scope.
-        ;; 2. Functions defined under the with statement also immune to
-        ;;    this setup, in which case dynamic scope is ignored in favor
-        ;;    of the with object.
-        (setf (js2-function-node-ignore-dynamic fn-node) t))
-
-    ;; dynamically bind all the per-function variables
-    (let ((js2-current-script-or-fn fn-node)
-          (js2-current-scope fn-node)
-          (js2-nesting-of-with 0)
-          (js2-end-flags 0)
-          js2-label-set
-          js2-loop-set
-          js2-loop-and-switch-set)
-
-      ;; parse params and function body
-      (js2-parse-function-params fn-node pos)
-      (js2-parse-function-body fn-node)
-      (if name
-          (js2-node-add-children fn-node name))
-
-      (js2-check-inconsistent-return-warning fn-node name)
-
-      ;; Function expressions define a name only in the body of the
-      ;; function, and only if not hidden by a parameter name
-      (if (and name
-               (eq synthetic-type 'FUNCTION_EXPRESSION)
-               (null (js2-scope-get-symbol js2-current-scope
-                                           (js2-name-node-name name))))
-          (js2-define-symbol js2-FUNCTION
-                             (js2-name-node-name name)
-                             fn-node))
-      (if (and name
-               (eq function-type 'FUNCTION_EXPRESSION_STATEMENT))
-          (js2-record-imenu-functions fn-node)))
-
-    (setf (js2-node-len fn-node) (- js2-ts-cursor pos)
-          (js2-function-node-member-expr fn-node) member-expr-node)  ; may be nil
-
-    ;; Rhino doesn't do this, but we need it for finding undeclared vars.
-    ;; We wait until after parsing the function to set its parent scope,
-    ;; since `js2-define-symbol' needs the defining-scope check to stop
-    ;; at the function boundary when checking for redeclarations.
-    (setf (js2-scope-parent-scope fn-node) js2-current-scope)
-
-    fn-node))
-
-(defun js2-parse-statements (&optional parent)
-  "Parse a statement list.  Last token consumed must be js2-LC.
-
-PARENT can be a `js2-block-node', in which case the statements are
-appended to PARENT.  Otherwise a new `js2-block-node' is created
-and returned.
-
-This function does not match the closing js2-RC: the caller
-matches the RC so it can provide a suitable error message if not
-matched.  This means it's up to the caller to set the length of
-the node to include the closing RC.  The node start pos is set to
-the absolute buffer start position, and the caller should fix it
-up to be relative to the parent node.  All children of this block
-node are given relative start positions and correct lengths."
-  (let ((pn (or parent (make-js2-block-node)))
-        tt)
-    (setf (js2-node-pos pn) js2-token-beg)
-    (while (and (> (setq tt (js2-peek-token)) js2-EOF)
-                (/= tt js2-RC))
-      (js2-block-node-push pn (js2-parse-statement)))
-    pn))
-
-(defun js2-parse-statement ()
-  (let (tt pn beg end)
-
-    ;; coarse-grained user-interrupt check - needs work
-    (and js2-parse-interruptable-p
-         (zerop (% (incf js2-parse-stmt-count)
-                   js2-statements-per-pause))
-         (input-pending-p)
-         (throw 'interrupted t))
-
-    (setq pn (js2-statement-helper))
-
-    ;; no-side-effects warning check
-    (unless (js2-node-has-side-effects pn)
-      (setq end (js2-node-end pn))
-      (save-excursion
-        (goto-char end)
-        (setq beg (max (js2-node-pos pn) (point-at-bol))))
-      (js2-add-strict-warning "msg.no.side.effects" nil beg end))
-
-    pn))
-
-;; These correspond to the switch cases in Parser.statementHelper
-(defconst js2-parsers
-  (let ((parsers (make-vector js2-num-tokens
-                                #'js2-parse-expr-stmt)))
-    (aset parsers js2-BREAK     #'js2-parse-break)
-    (aset parsers js2-CONST     #'js2-parse-const-var)
-    (aset parsers js2-CONTINUE  #'js2-parse-continue)
-    (aset parsers js2-DEBUGGER  #'js2-parse-debugger)
-    (aset parsers js2-DEFAULT   #'js2-parse-default-xml-namespace)
-    (aset parsers js2-DO        #'js2-parse-do)
-    (aset parsers js2-FOR       #'js2-parse-for)
-    (aset parsers js2-FUNCTION  #'js2-function-parser)
-    (aset parsers js2-IF        #'js2-parse-if)
-    (aset parsers js2-LC        #'js2-parse-block)
-    (aset parsers js2-LET       #'js2-parse-let-stmt)
-    (aset parsers js2-NAME      #'js2-parse-name-or-label)
-    (aset parsers js2-RETURN    #'js2-parse-ret-yield)
-    (aset parsers js2-SEMI      #'js2-parse-semi)
-    (aset parsers js2-SWITCH    #'js2-parse-switch)
-    (aset parsers js2-THROW     #'js2-parse-throw)
-    (aset parsers js2-TRY       #'js2-parse-try)
-    (aset parsers js2-VAR       #'js2-parse-const-var)
-    (aset parsers js2-WHILE     #'js2-parse-while)
-    (aset parsers js2-WITH      #'js2-parse-with)
-    (aset parsers js2-YIELD     #'js2-parse-ret-yield)
-    parsers)
-  "A vector mapping token types to parser functions.")
-
-(defsubst js2-parse-warn-missing-semi (beg end)
-  (and js2-mode-show-strict-warnings
-       js2-strict-missing-semi-warning
-       (js2-add-strict-warning
-        "msg.missing.semi" nil
-        ;; back up to beginning of statement or line
-        (max beg (save-excursion
-                   (goto-char end)
-                   (point-at-bol)))
-        end)))
-
-(defconst js2-no-semi-insertion
-  (list js2-IF
-        js2-SWITCH
-        js2-WHILE
-        js2-DO
-        js2-FOR
-        js2-TRY
-        js2-WITH
-        js2-LC
-        js2-ERROR
-        js2-SEMI
-        js2-FUNCTION)
-  "List of tokens that don't do automatic semicolon insertion.")
-
-(defconst js2-autoinsert-semi-and-warn
-  (list js2-ERROR js2-EOF js2-RC))
-
-(defun js2-statement-helper ()
-  (let* ((tt (js2-peek-token))
-         (first-tt tt)
-         (beg js2-token-beg)
-         (parser (if (= tt js2-ERROR)
-                     #'js2-parse-semi
-                   (aref js2-parsers tt)))
-         pn
-         tt-flagged)
-    ;; If the statement is set, then it's been told its label by now.
-    (and js2-labeled-stmt
-         (js2-labeled-stmt-node-stmt js2-labeled-stmt)
-         (setq js2-labeled-stmt nil))
-
-    (setq pn (funcall parser)
-          tt-flagged (js2-peek-flagged-token)
-          tt (logand tt-flagged js2-clear-ti-mask))
-
-    ;; Don't do auto semi insertion for certain statement types.
-    (unless (or (memq first-tt js2-no-semi-insertion)
-                (js2-labeled-stmt-node-p pn))
-      (cond
-       ((= tt js2-SEMI)
-        ;; Consume ';' as a part of expression
-        (js2-consume-token)
-        ;; extend the node bounds to include the semicolon.
-        (setf (js2-node-len pn) (- js2-token-end beg)))
-       ((memq tt js2-autoinsert-semi-and-warn)
-        ;; Autoinsert ;
-        (js2-parse-warn-missing-semi beg (js2-node-end pn)))
-       (t
-        (if (js2-flag-not-set-p tt-flagged js2-ti-after-eol)
-            ;; Report error if no EOL or autoinsert ';' otherwise
-            (js2-report-error "msg.no.semi.stmt")
-          (js2-parse-warn-missing-semi beg (js2-node-end pn))))))
-    pn))
-
-(defun js2-parse-condition ()
-  "Parse a parenthesized boolean expression, e.g. in an if- or while-stmt.
-The parens are discarded and the expression node is returned.
-The `pos' field of the return value is set to an absolute position
-that must be fixed up by the caller.
-Return value is a list (EXPR LP RP), with absolute paren positions."
-  (let (pn lp rp)
-    (if (js2-must-match js2-LP "msg.no.paren.cond")
-        (setq lp js2-token-beg))
-    (setq pn (js2-parse-expr))
-    (if (js2-must-match js2-RP "msg.no.paren.after.cond")
-        (setq rp js2-token-beg))
-    ;; Report strict warning on code like "if (a = 7) ..."
-    (if (and js2-strict-cond-assign-warning
-             (js2-assign-node-p pn))
-        (js2-add-strict-warning "msg.equal.as.assign" nil
-                                (js2-node-pos pn)
-                                (+ (js2-node-pos pn)
-                                   (js2-node-len pn))))
-    (list pn lp rp)))
-
-(defun js2-parse-if ()
-  "Parser for if-statement.  Last matched token must be js2-IF."
-  (let ((pos js2-token-beg)
-        cond
-        if-true
-        if-false
-        else-pos
-        end
-        pn)
-    (js2-consume-token)
-    (setq cond (js2-parse-condition)
-          if-true (js2-parse-statement)
-          if-false (if (js2-match-token js2-ELSE)
-                       (progn
-                         (setq else-pos (- js2-token-beg pos))
-                         (js2-parse-statement)))
-          end (js2-node-end (or if-false if-true))
-          pn (make-js2-if-node :pos pos
-                               :len (- end pos)
-                               :condition (car cond)
-                               :then-part if-true
-                               :else-part if-false
-                               :else-pos else-pos
-                               :lp (js2-relpos (second cond) pos)
-                               :rp (js2-relpos (third cond) pos)))
-    (js2-node-add-children pn (car cond) if-true if-false)
-    pn))
-
-(defun js2-parse-switch ()
-  "Parser for if-statement.  Last matched token must be js2-SWITCH."
-  (let ((pos js2-token-beg)
-        tt
-        pn
-        discriminant
-        has-default
-        case-expr
-        case-node
-        case-pos
-        cases
-        stmt
-        lp
-        rp)
-    (js2-consume-token)
-    (if (js2-must-match js2-LP "msg.no.paren.switch")
-        (setq lp js2-token-beg))
-    (setq discriminant (js2-parse-expr)
-          pn (make-js2-switch-node :discriminant discriminant
-                                   :pos pos
-                                   :lp (js2-relpos lp pos)))
-    (js2-node-add-children pn discriminant)
-    (js2-enter-switch pn)
-    (unwind-protect
-        (progn
-          (if (js2-must-match js2-RP "msg.no.paren.after.switch")
-              (setf (js2-switch-node-rp pn) (- js2-token-beg pos)))
-          (js2-must-match js2-LC "msg.no.brace.switch")
-          (catch 'break
-            (while t
-              (setq tt (js2-next-token)
-                    case-pos js2-token-beg)
-              (cond
-               ((= tt js2-RC)
-                (setf (js2-node-len pn) (- js2-token-end pos))
-                (throw 'break nil))  ; done
-
-               ((= tt js2-CASE)
-                (setq case-expr (js2-parse-expr))
-                (js2-must-match js2-COLON "msg.no.colon.case"))
-
-               ((= tt js2-DEFAULT)
-                (if has-default
-                    (js2-report-error "msg.double.switch.default"))
-                (setq has-default t
-                      case-expr nil)
-                (js2-must-match js2-COLON "msg.no.colon.case"))
-
-               (t
-                (js2-report-error "msg.bad.switch")
-                (throw 'break nil)))
-
-              (setq case-node (make-js2-case-node :pos case-pos
-                                                  :len (- js2-token-end case-pos)
-                                                  :expr case-expr))
-              (js2-node-add-children case-node case-expr)
-              (while (and (/= (setq tt (js2-peek-token)) js2-RC)
-                          (/= tt js2-CASE)
-                          (/= tt js2-DEFAULT)
-                          (/= tt js2-EOF))
-                (setf stmt (js2-parse-statement)
-                      (js2-node-len case-node) (- (js2-node-end stmt) case-pos))
-                (js2-block-node-push case-node stmt))
-              (push case-node cases)))
-          ;; add cases last, as pushing reverses the order to be correct
-          (dolist (kid cases)
-            (js2-node-add-children pn kid)
-            (push kid (js2-switch-node-cases pn)))
-          pn)  ; return value
-      (js2-exit-switch))))
-
-(defun js2-parse-while ()
-  "Parser for while-statement.  Last matched token must be js2-WHILE."
-  (let ((pos js2-token-beg)
-        (pn (make-js2-while-node))
-        cond
-        body)
-    (js2-consume-token)
-    (js2-enter-loop pn)
-    (unwind-protect
-        (progn
-          (setf cond (js2-parse-condition)
-                (js2-while-node-condition pn) (car cond)
-                body (js2-parse-statement)
-                (js2-while-node-body pn) body
-                (js2-node-len pn) (- (js2-node-end body) pos)
-                (js2-while-node-lp pn) (js2-relpos (second cond) pos)
-                (js2-while-node-rp pn) (js2-relpos (third cond) pos))
-          (js2-node-add-children pn body (car cond)))
-      (js2-exit-loop))
-    pn))
-
-(defun js2-parse-do ()
-  "Parser for do-statement.  Last matched token must be js2-DO."
-  (let ((pos js2-token-beg)
-        (pn (make-js2-do-node))
-        cond
-        body
-        end)
-    (js2-consume-token)
-    (js2-enter-loop pn)
-    (unwind-protect
-        (progn
-          (setq body (js2-parse-statement))
-          (js2-must-match js2-WHILE "msg.no.while.do")
-          (setf (js2-do-node-while-pos pn) (- js2-token-beg pos)
-                cond (js2-parse-condition)
-                (js2-do-node-condition pn) (car cond)
-                (js2-do-node-body pn) body
-                end js2-ts-cursor
-                (js2-do-node-lp pn) (js2-relpos (second cond) pos)
-                (js2-do-node-rp pn) (js2-relpos (third cond) pos))
-          (js2-node-add-children pn (car cond) body))
-      (js2-exit-loop))
-    ;; Always auto-insert semicolon to follow SpiderMonkey:
-    ;; It is required by ECMAScript but is ignored by the rest of
-    ;; world; see bug 238945
-    (if (js2-match-token js2-SEMI)
-        (setq end js2-ts-cursor))
-    (setf (js2-node-len pn) (- end pos))
-    pn))
-
-(defun js2-parse-for ()
-  "Parser for for-statement.  Last matched token must be js2-FOR.
-Parses for, for-in, and for each-in statements."
-  (let ((for-pos js2-token-beg)
-        pn
-        is-for-each
-        is-for-in
-        in-pos
-        each-pos
-        tmp-pos
-        init  ; Node init is also foo in 'foo in object'
-        cond  ; Node cond is also object in 'foo in object'
-        incr  ; 3rd section of for-loop initializer
-        body
-        tt
-        lp
-        rp)
-    (js2-consume-token)
-    ;; See if this is a for each () instead of just a for ()
-    (when (js2-match-token js2-NAME)
-      (if (string= "each" js2-ts-string)
-          (progn
-            (setq is-for-each t
-                  each-pos (- js2-token-beg for-pos)) ; relative
-            (js2-record-face 'font-lock-keyword-face))
-        (js2-report-error "msg.no.paren.for")))
-
-    (if (js2-must-match js2-LP "msg.no.paren.for")
-        (setq lp (- js2-token-beg for-pos)))
-    (setq tt (js2-peek-token))
-
-    ;; parse init clause
-    (let ((js2-in-for-init t))  ; set as dynamic variable
-      (cond
-       ((= tt js2-SEMI)
-        (setq init (make-js2-empty-expr-node)))
-       ((or (= tt js2-VAR) (= tt js2-LET))
-        (js2-consume-token)
-        (setq init (js2-parse-variables tt js2-token-beg)))
-       (t
-        (setq init (js2-parse-expr)))))
-
-    (if (js2-match-token js2-IN)
-        (setq is-for-in t
-              in-pos (- js2-token-beg for-pos)
-              cond (js2-parse-expr))  ; object over which we're iterating
-      ;; else ordinary for loop - parse cond and incr
-      (js2-must-match js2-SEMI "msg.no.semi.for")
-      (setq cond (if (= (js2-peek-token) js2-SEMI)
-                     (make-js2-empty-expr-node) ; no loop condition
-                   (js2-parse-expr)))
-      (js2-must-match js2-SEMI "msg.no.semi.for.cond")
-      (setq tmp-pos js2-token-end
-            incr (if (= (js2-peek-token) js2-RP)
-                     (make-js2-empty-expr-node :pos tmp-pos)
-                   (js2-parse-expr))))
-
-    (if (js2-must-match js2-RP "msg.no.paren.for.ctrl")
-        (setq rp (- js2-token-beg for-pos)))
-    (if (not is-for-in)
-        (setq pn (make-js2-for-node :init init
-                                    :condition cond
-                                    :update incr
-                                    :lp lp
-                                    :rp rp))
-      ;; cond could be null if 'in obj' got eaten by the init node.
-      (if (js2-infix-node-p init)
-          ;; it was (foo in bar) instead of (var foo in bar)
-          (setq cond (js2-infix-node-right init)
-                init (js2-infix-node-left init))
-        (if (and (js2-var-decl-node-p init)
-                 (> (length (js2-var-decl-node-kids init)) 1))
-            (js2-report-error "msg.mult.index")))
-
-      (setq pn (make-js2-for-in-node :iterator init
-                                     :object cond
-                                     :in-pos in-pos
-                                     :foreach-p is-for-each
-                                     :each-pos each-pos
-                                     :lp lp
-                                     :rp rp)))
-    (unwind-protect
-        (progn
-          (js2-enter-loop pn)
-          ;; We have to parse the body -after- creating the loop node,
-          ;; so that the loop node appears in the js2-loop-set, allowing
-          ;; break/continue statements to find the enclosing loop.
-          (setf body (js2-parse-statement)
-                (js2-loop-node-body pn) body
-                (js2-node-pos pn) for-pos
-                (js2-node-len pn) (- (js2-node-end body) for-pos))
-          (js2-node-add-children pn init cond incr body))
-      ;; finally
-      (js2-exit-loop))
-    pn))
-
-(defun js2-parse-try ()
-  "Parser for try-statement.  Last matched token must be js2-TRY."
-  (let ((try-pos js2-token-beg)
-        try-end
-        try-block
-        catch-blocks
-        finally-block
-        saw-default-catch
-        peek
-        var-name
-        catch-cond
-        catch-node
-        guard-kwd
-        catch-pos
-        finally-pos
-        pn
-        block
-        lp
-        rp)
-    (js2-consume-token)
-    (if (/= (js2-peek-token) js2-LC)
-        (js2-report-error "msg.no.brace.try"))
-    (setq try-block (js2-parse-statement)
-          try-end (js2-node-end try-block)
-          peek (js2-peek-token))
-    (cond
-     ((= peek js2-CATCH)
-      (while (js2-match-token js2-CATCH)
-        (setq catch-pos js2-token-beg
-              guard-kwd nil
-              catch-cond nil
-              lp nil
-              rp nil)
-        (if saw-default-catch
-            (js2-report-error "msg.catch.unreachable"))
-        (if (js2-must-match js2-LP "msg.no.paren.catch")
-            (setq lp (- js2-token-beg catch-pos)))
-
-        (js2-must-match js2-NAME "msg.bad.catchcond")
-        (setq var-name (js2-create-name-node))
-
-        (if (js2-match-token js2-IF)
-            (setq guard-kwd (- js2-token-beg catch-pos)
-                  catch-cond (js2-parse-expr))
-          (setq saw-default-catch t))
-
-        (if (js2-must-match js2-RP "msg.bad.catchcond")
-            (setq rp (- js2-token-beg catch-pos)))
-        (js2-must-match js2-LC "msg.no.brace.catchblock")
-
-        (setq block (js2-parse-statements)
-              try-end (js2-node-end block)
-              catch-node (make-js2-catch-node :pos catch-pos
-                                              :var-name var-name
-                                              :guard-expr catch-cond
-                                              :guard-kwd guard-kwd
-                                              :block block
-                                              :lp lp
-                                              :rp rp))
-        (if (js2-must-match js2-RC "msg.no.brace.after.body")
-            (setq try-end js2-token-beg))
-        (setf (js2-node-len block) (- try-end (js2-node-pos block))
-              (js2-node-len catch-node) (- try-end catch-pos))
-        (js2-node-add-children catch-node var-name catch-cond block)
-        (push catch-node catch-blocks)))
-
-     ((/= peek js2-FINALLY)
-      (js2-must-match js2-FINALLY "msg.try.no.catchfinally"
-                      (js2-node-pos try-block)
-                      (- (setq try-end (js2-node-end try-block))
-                         (js2-node-pos try-block)))))
-
-    (when (js2-match-token js2-FINALLY)
-      (setq finally-pos js2-token-beg
-            block (js2-parse-statement)
-            try-end (js2-node-end block)
-            finally-block (make-js2-finally-node :pos finally-pos
-                                                 :len (- try-end finally-pos)
-                                                 :body block))
-      (js2-node-add-children finally-block block))
-
-    (setq pn (make-js2-try-node :pos try-pos
-                                :len (- try-end try-pos)
-                                :try-block try-block
-                                :finally-block finally-block))
-    (js2-node-add-children pn try-block finally-block)
-
-    ;; push them onto the try-node, which reverses and corrects their order
-    (dolist (cb catch-blocks)
-      (js2-node-add-children pn cb)
-      (push cb (js2-try-node-catch-clauses pn)))
-    pn))
-
-(defun js2-parse-throw ()
-  "Parser for throw-statement.  Last matched token must be js2-THROW."
-  (let ((pos js2-token-beg)
-        expr
-        pn)
-    (js2-consume-token)
-    (if (= (js2-peek-token-or-eol) js2-EOL)
-        ;; ECMAScript does not allow new lines before throw expression,
-        ;; see bug 256617
-        (js2-report-error "msg.bad.throw.eol"))
-    (setq expr (js2-parse-expr)
-          pn (make-js2-throw-node :pos pos
-                                  :len (- (js2-node-end expr) pos)
-                                  :expr expr))
-    (js2-node-add-children pn expr)
-    pn))
-
-(defsubst js2-match-jump-label-name (label-name)
-  "If break/continue specified a label, return that label's labeled stmt.
-Returns the corresponding `js2-labeled-stmt-node', or if LABEL-NAME
-does not match an existing label, reports an error and returns nil."
-  (let ((bundle (cdr (assoc label-name js2-label-set))))
-    (if (null bundle)
-        (js2-report-error "msg.undef.label"))
-    bundle))
-
-(defun js2-parse-break ()
-  "Parser for break-statement.  Last matched token must be js2-BREAK."
-  (let ((pos js2-token-beg)
-        (end js2-token-end)
-        break-target ; statement to break from
-        break-label  ; in "break foo", name-node representing the foo
-        labels       ; matching labeled statement to break to
-        pn)
-    (js2-consume-token)  ; `break'
-    (when (eq (js2-peek-token-or-eol) js2-NAME)
-      (js2-consume-token)
-      (setq break-label (js2-create-name-node)
-            end (js2-node-end break-label)
-            ;; matchJumpLabelName only matches if there is one
-            labels (js2-match-jump-label-name js2-ts-string)
-            break-target (if labels (car (js2-labeled-stmt-node-labels labels)))))
-
-    (unless (or break-target break-label)
-      ;; no break target specified - try for innermost enclosing loop/switch
-      (if (null js2-loop-and-switch-set)
-          (unless break-label
-            (js2-report-error "msg.bad.break" nil pos (length "break")))
-        (setq break-target (car js2-loop-and-switch-set))))
-
-    (setq pn (make-js2-break-node :pos pos
-                                  :len (- end pos)
-                                  :label break-label
-                                  :target break-target))
-    (js2-node-add-children pn break-label)  ; but not break-target
-    pn))
-
-(defun js2-parse-continue ()
-  "Parser for continue-statement.  Last matched token must be js2-CONTINUE."
-  (let ((pos js2-token-beg)
-        (end js2-token-end)
-        label   ; optional user-specified label, a `js2-name-node'
-        labels  ; current matching labeled stmt, if any
-        target  ; the `js2-loop-node' target of this continue stmt
-        pn)
-    (js2-consume-token)  ; `continue'
-    (when (= (js2-peek-token-or-eol) js2-NAME)
-      (js2-consume-token)
-      (setq label (js2-create-name-node)
-            end (js2-node-end label)
-            ;; matchJumpLabelName only matches if there is one
-            labels (js2-match-jump-label-name js2-ts-string)))
-    (cond
-     ((null labels)  ; no current label to go to
-      (if (null js2-loop-set)  ; no loop to continue to
-          (js2-report-error "msg.continue.outside" nil pos
-                            (length "continue"))
-        (setq target (car js2-loop-set))))  ; innermost enclosing loop
-     (t
-      (if (js2-loop-node-p (js2-labeled-stmt-node-stmt labels))
-          (setq target (js2-labeled-stmt-node-stmt labels))
-        (js2-report-error "msg.continue.nonloop" nil pos (- end pos)))))
-
-    (setq pn (make-js2-continue-node :pos pos
-                                     :len (- end pos)
-                                     :label label
-                                     :target target))
-    (js2-node-add-children pn label)  ; but not target - it's not our child
-    pn))
-
-(defun js2-parse-with ()
-  "Parser for with-statement.  Last matched token must be js2-WITH."
-  (js2-consume-token)
-  (let ((pos js2-token-beg)
-        obj body pn lp rp)
-
-    (if (js2-must-match js2-LP "msg.no.paren.with")
-        (setq lp js2-token-beg))
-
-    (setq obj (js2-parse-expr))
-
-    (if (js2-must-match js2-RP "msg.no.paren.after.with")
-        (setq rp js2-token-beg))
-
-    (let ((js2-nesting-of-with (1+ js2-nesting-of-with)))
-        (setq body (js2-parse-statement)))
-
-    (setq pn (make-js2-with-node :pos pos
-                                 :len (- (js2-node-end body) pos)
-                                 :object obj
-                                 :body body
-                                 :lp (js2-relpos lp pos)
-                                 :rp (js2-relpos rp pos)))
-    (js2-node-add-children pn obj body)
-    pn))
-
-(defun js2-parse-const-var ()
-  "Parser for var- or const-statement.
-Last matched token must be js2-CONST or js2-VAR."
-  (let ((tt (js2-peek-token))
-        (pos js2-token-beg)
-        expr
-        pn)
-    (js2-consume-token)
-    (setq expr (js2-parse-variables tt js2-token-beg)
-          pn (make-js2-expr-stmt-node :pos pos
-                                      :len (- (js2-node-end expr) pos)
-                                      :expr expr))
-    (js2-node-add-children pn expr)
-    pn))
-
-(defsubst js2-wrap-with-expr-stmt (pos expr &optional add-child)
-  (let ((pn (make-js2-expr-stmt-node :pos pos
-                                     :len (js2-node-len expr)
-                                     :type (if (js2-inside-function)
-                                               js2-EXPR_VOID
-                                             js2-EXPR_RESULT)
-                                     :expr expr)))
-    (if add-child
-        (js2-node-add-children pn expr))
-    pn))
-
-(defun js2-parse-let-stmt ()
-  "Parser for let-statement.  Last matched token must be js2-LET."
-  (js2-consume-token)
-  (let ((pos js2-token-beg)
-        expr
-        pn)
-    (if (= (js2-peek-token) js2-LP)
-        ;; let expression in statement context
-        (setq expr (js2-parse-let pos 'statement)
-              pn (js2-wrap-with-expr-stmt pos expr t))
-      ;; else we're looking at a statement like let x=6, y=7;
-      (setf expr (js2-parse-variables js2-LET pos)
-            pn (js2-wrap-with-expr-stmt pos expr t)
-            (js2-node-type pn) js2-EXPR_RESULT))
-    pn))
-
-(defun js2-parse-ret-yield ()
-  (js2-parse-return-or-yield (js2-peek-token) nil))
-
-(defconst js2-parse-return-stmt-enders
-  (list js2-SEMI js2-RC js2-EOF js2-EOL js2-ERROR js2-RB js2-RP js2-YIELD))
-
-(defsubst js2-now-all-set (before after mask)
-  "Return whether or not the bits in the mask have changed to all set.
-BEFORE is bits before change, AFTER is bits after change, and MASK is
-the mask for bits.  Returns t if all the bits in the mask are set in AFTER
-but not BEFORE."
-  (and (/= (logand before mask) mask)
-       (= (logand after mask) mask)))
-
-(defun js2-parse-return-or-yield (tt expr-context)
-  (let ((pos js2-token-beg)
-        (end js2-token-end)
-        (before js2-end-flags)
-        (inside-function (js2-inside-function))
-        e
-        ret
-        name)
-    (unless inside-function
-      (js2-report-error (if (eq tt js2-RETURN)
-                            "msg.bad.return"
-                          "msg.bad.yield")))
-    (js2-consume-token)
-    ;; This is ugly, but we don't want to require a semicolon.
-    (unless (memq (js2-peek-token-or-eol) js2-parse-return-stmt-enders)
-      (setq e (js2-parse-expr)
-            end (js2-node-end e)))
-    (cond
-     ((eq tt js2-RETURN)
-      (js2-set-flag js2-end-flags (if (null e)
-                                      js2-end-returns
-                                    js2-end-returns-value))
-      (setq ret (make-js2-return-node :pos pos
-                                      :len (- end pos)
-                                      :retval e))
-      (js2-node-add-children ret e)
-      ;; See if we need a strict mode warning.
-      ;; TODO:  The analysis done by `js2-has-consistent-return-usage' is
-      ;; more thorough and accurate than this before/after flag check.
-      ;; E.g. if there's a finally-block that always returns, we shouldn't
-      ;; show a warning generated by inconsistent returns in the catch blocks.
-      ;; Basically `js2-has-consistent-return-usage' needs to keep more state,
-      ;; so we know which returns/yields to highlight, and we should get rid of
-      ;; all the checking in `js2-parse-return-or-yield'.
-      (if (and js2-strict-inconsistent-return-warning
-               (js2-now-all-set before js2-end-flags
-                                (logior js2-end-returns js2-end-returns-value)))
-          (js2-add-strict-warning "msg.return.inconsistent" nil pos end)))
-     (t
-      (unless (js2-inside-function)
-        (js2-report-error "msg.bad.yield"))
-      (js2-set-flag js2-end-flags js2-end-yields)
-      (setq ret (make-js2-yield-node :pos pos
-                                     :len (- end pos)
-                                     :value e))
-      (js2-node-add-children ret e)
-      (unless expr-context
-        (setq e ret
-              ret (js2-wrap-with-expr-stmt pos e t))
-      (js2-set-requires-activation)
-      (js2-set-is-generator))))
-
-    ;; see if we are mixing yields and value returns.
-    (when (and inside-function
-               (js2-now-all-set before js2-end-flags
-                                (logior js2-end-yields js2-end-returns-value)))
-      (setq name (js2-function-name js2-current-script-or-fn))
-      (if (zerop (length name))
-          (js2-report-error "msg.anon.generator.returns" nil pos (- end pos))
-        (js2-report-error "msg.generator.returns" name pos (- end pos))))
-
-    ret))
-
-(defun js2-parse-debugger ()
-  (js2-consume-token)
-  (make-js2-keyword-node :type js2-DEBUGGER))
-
-(defun js2-parse-block ()
-  "Parser for a curly-delimited statement block.
-Last token matched must be js2-LC."
-  (let ((pos js2-token-beg)
-        (pn (make-js2-scope)))
-    (js2-consume-token)
-    (js2-push-scope pn)
-    (unwind-protect
-        (progn
-          (js2-parse-statements pn)
-          (js2-must-match js2-RC "msg.no.brace.block")
-          (setf (js2-node-len pn) (- js2-token-end pos)))
-      (js2-pop-scope))
-    pn))
-
-;; for js2-ERROR too, to have a node for error recovery to work on
-(defun js2-parse-semi ()
-  "Parse a statement or handle an error.
-Last matched token is js-SEMI or js-ERROR."
-  (let ((tt (js2-peek-token)) pos len)
-    (js2-consume-token)
-    (if (eq tt js2-SEMI)
-        (make-js2-empty-expr-node :len 1)
-      (setq pos js2-token-beg
-            len (- js2-token-beg pos))
-      (js2-report-error "msg.syntax" nil pos len)
-      (make-js2-error-node :pos pos :len len))))
-
-(defun js2-parse-default-xml-namespace ()
-  "Parse a `default xml namespace = <expr>' e4x statement."
-  (let ((pos js2-token-beg)
-        end len expr unary es)
-    (js2-consume-token)
-    (js2-must-have-xml)
-    (js2-set-requires-activation)
-    (setq len (- js2-ts-cursor pos))
-    (unless (and (js2-match-token js2-NAME)
-                 (string= js2-ts-string "xml"))
-      (js2-report-error "msg.bad.namespace" nil pos len))
-    (unless (and (js2-match-token js2-NAME)
-                 (string= js2-ts-string "namespace"))
-      (js2-report-error "msg.bad.namespace" nil pos len))
-    (unless (js2-match-token js2-ASSIGN)
-      (js2-report-error "msg.bad.namespace" nil pos len))
-    (setq expr (js2-parse-expr)
-          end (js2-node-end expr)
-          unary (make-js2-unary-node :type js2-DEFAULTNAMESPACE
-                                     :pos pos
-                                     :len (- end pos)
-                                     :operand expr))
-    (js2-node-add-children unary expr)
-    (make-js2-expr-stmt-node :pos pos
-                             :len (- end pos)
-                             :expr unary)))
-
-(defun js2-record-label (label bundle)
-  ;; current token should be colon that `js2-parse-primary-expr' left untouched
-  (js2-consume-token)
-  (let ((name (js2-label-node-name label))
-        labeled-stmt
-        dup)
-    (when (setq labeled-stmt (cdr (assoc name js2-label-set)))
-      ;; flag both labels if possible when used in editing mode
-      (if (and js2-parse-ide-mode
-               (setq dup (js2-get-label-by-name labeled-stmt name)))
-          (js2-report-error "msg.dup.label" nil
-                            (js2-node-abs-pos dup) (js2-node-len dup)))
-      (js2-report-error "msg.dup.label" nil
-                        (js2-node-pos label) (js2-node-len label)))
-    (js2-labeled-stmt-node-add-label bundle label)
-    (js2-node-add-children bundle label)
-    ;; Add one reference to the bundle per label in `js2-label-set'
-    (push (cons name bundle) js2-label-set)))
-
-(defun js2-parse-name-or-label ()
-  "Parser for identifier or label.  Last token matched must be js2-NAME.
-Called when we found a name in a statement context.  If it's a label, we gather
-up any following labels and the next non-label statement into a
-`js2-labeled-stmt-node' bundle and return that.  Otherwise we parse an
-expression and return it wrapped in a `js2-expr-stmt-node'."
-  (let ((pos js2-token-beg)
-        (end js2-token-end)
-        expr
-        stmt
-        pn
-        bundle
-        (continue t))
-    ;; set check for label and call down to `js2-parse-primary-expr'
-    (js2-set-check-for-label)
-    (setq expr (js2-parse-expr))
-
-    (if (/= (js2-node-type expr) js2-LABEL)
-        ;; Parsed non-label expression - wrap with expression stmt.
-        (setq pn (js2-wrap-with-expr-stmt pos expr t))
-
-      ;; else parsed a label
-      (setq bundle (make-js2-labeled-stmt-node :pos pos))
-      (js2-record-label expr bundle)
-
-      ;; look for more labels
-      (while (and continue (= (js2-peek-token) js2-NAME))
-        (js2-set-check-for-label)
-        (setq expr (js2-parse-expr))
-        (if (/= (js2-node-type expr) js2-LABEL)
-            (setq stmt (js2-wrap-with-expr-stmt pos expr t)
-                  continue nil)
-          (js2-record-label expr bundle)))
-
-      ;; no more labels; now parse the labeled statement
-      (unwind-protect
-            (unless stmt
-              (let ((js2-labeled-stmt bundle))  ; bind dynamically
-                (setq stmt (js2-statement-helper))))
-        ;; remove the labels for this statement from the global set
-        (dolist (label (js2-labeled-stmt-node-labels bundle))
-          (setq js2-label-set (remove label js2-label-set))))
-
-      (setf (js2-labeled-stmt-node-stmt bundle) stmt)
-      (js2-node-add-children bundle stmt)
-      bundle)))
-
-(defun js2-parse-expr-stmt ()
-  "Default parser in statement context, if no recognized statement found."
-  (js2-wrap-with-expr-stmt js2-token-beg (js2-parse-expr) t))
-
-(defun js2-parse-variables (decl-type pos)
-  "Parse a comma-separated list of variable declarations.
-Could be a 'var', 'const' or 'let' expression, possibly in a for-loop initializer.
-
-DECL-TYPE is a token value: either VAR, CONST, or LET depending on context.
-For 'var' or 'const', the keyword should be the token last scanned.
-
-POS is the position where the node should start. It's sometimes the
-var/const/let keyword, and other times the beginning of the first token
-in the first variable declaration.
-
-Returns the parsed `js2-var-decl-node' expression node."
-  (let* ((result (make-js2-var-decl-node :decl-type decl-type
-                                         :pos pos))
-         destructuring
-         kid-pos
-         tt
-         init
-         name
-         end
-         nbeg nend
-         vi
-         (continue t))
-    ;; Example:
-    ;; var foo = {a: 1, b: 2}, bar = [3, 4];
-    ;; var {b: s2, a: s1} = foo, x = 6, y, [s3, s4] = bar;
-    (while continue
-      (setq destructuring nil
-            name nil
-            tt (js2-peek-token)
-            kid-pos js2-token-beg
-            end js2-token-end
-            init nil)
-      (if (or (= tt js2-LB) (= tt js2-LC))
-          ;; Destructuring assignment, e.g., var [a, b] = ...
-          (setq destructuring (js2-parse-primary-expr)
-                end (js2-node-end destructuring))
-        ;; Simple variable name
-        (when (js2-must-match js2-NAME "msg.bad.var")
-          (setq name (js2-create-name-node)
-                nbeg js2-token-beg
-                nend js2-token-end
-                end nend)
-          (js2-define-symbol decl-type js2-ts-string name js2-in-for-init)))
-
-      (when (js2-match-token js2-ASSIGN)
-        (setq init (js2-parse-assign-expr)
-              end (js2-node-end init))
-        (if (and js2-parse-ide-mode
-                 (or (js2-object-node-p init)
-                     (js2-function-node-p init)))
-            (js2-record-imenu-functions init name)))
-
-      (when name
-        (js2-set-face nbeg nend (if (js2-function-node-p init)
-                                    'font-lock-function-name-face
-                                  'font-lock-variable-name-face)
-                      'record))
-
-      (setq vi (make-js2-var-init-node :pos kid-pos
-                                       :len (- end kid-pos)
-                                       :type decl-type))
-      (if destructuring
-          (progn
-            (if (and (null init) (not js2-in-for-init))
-                (js2-report-error "msg.destruct.assign.no.init"))
-            (setf (js2-var-init-node-target vi) destructuring))
-        (setf (js2-var-init-node-target vi) name))
-      (setf (js2-var-init-node-initializer vi) init)
-      (js2-node-add-children vi name destructuring init)
-
-      (js2-block-node-push result vi)
-      (unless (js2-match-token js2-COMMA)
-        (setq continue nil)))
-
-    (setf (js2-node-len result) (- end pos))
-    result))
-
-(defun js2-parse-let (pos &optional stmt-p)
-  "Parse a let expression or statement.
-A let-expression is of the form `let (vars) expr'.
-A let-statment is of the form `let (vars) {statements}'.
-The third form of let is a variable declaration list, handled
-by `js2-parse-variables'."
-  (let ((pn (make-js2-let-node :pos pos))
-        beg vars body)
-    (if (js2-must-match js2-LP "msg.no.paren.after.let")
-        (setf (js2-let-node-lp pn) (- js2-token-beg pos)))
-    (js2-push-scope pn)
-    (unwind-protect
-        (progn
-          (setq vars (js2-parse-variables js2-LET js2-token-beg))
-          (if (js2-must-match js2-RP "msg.no.paren.let")
-              (setf (js2-let-node-rp pn) (- js2-token-beg pos)))
-          (if (and stmt-p (eq (js2-peek-token) js2-LC))
-              ;; let statement
-              (progn
-                (js2-consume-token)
-                (setf beg js2-token-beg  ; position stmt at LC
-                      body (js2-parse-statements))
-                (js2-must-match js2-RC "msg.no.curly.let")
-                (setf (js2-node-len body) (- js2-token-end beg)
-                      (js2-node-len pn) (- js2-token-end pos)
-                      (js2-let-node-body pn) body
-                      (js2-node-type pn) js2-LET))
-            ;; let expression
-            (setf body (js2-parse-expr)
-                  (js2-node-len pn) (- (js2-node-end body) pos)
-                  (js2-let-node-body pn) body))
-          (js2-node-add-children pn vars body))
-      (js2-pop-scope))
-    pn))
-
-(defsubst js2-define-new-symbol (decl-type name node)
-  (js2-scope-put-symbol js2-current-scope
-                        name
-                        (make-js2-symbol decl-type name node)))
-
-(defun js2-define-symbol (decl-type name &optional node ignore-not-in-block)
-  "Define a symbol in the current scope.
-If NODE is non-nil, it is the AST node associated with the symbol."
-  (let* ((defining-scope (js2-get-defining-scope js2-current-scope name))
-         (symbol (if defining-scope
-                     (js2-scope-get-symbol defining-scope name)))
-         (sdt (if symbol (js2-symbol-decl-type symbol) -1)))
-    (cond
-     ((and symbol ; already defined
-           (or (= sdt js2-CONST) ; old version is const
-               (= decl-type js2-CONST) ; new version is const
-               ;; two let-bound vars in this block have same name
-               (and (= sdt js2-LET)
-                    (eq defining-scope js2-current-scope))))
-      (js2-report-error
-       (cond
-        ((= sdt js2-CONST) "msg.const.redecl")
-        ((= sdt js2-LET) "msg.let.redecl")
-        ((= sdt js2-VAR) "msg.var.redecl")
-        ((= sdt js2-FUNCTION) "msg.function.redecl")
-        (t "msg.parm.redecl"))
-       name))
-
-     ((= decl-type js2-LET)
-      (if (and (not ignore-not-in-block)
-               (or (= (js2-node-type js2-current-scope) js2-IF)
-                   (js2-loop-node-p js2-current-scope)))
-          (js2-report-error "msg.let.decl.not.in.block")
-        (js2-define-new-symbol decl-type name node)))
-
-     ((or (= decl-type js2-VAR)
-          (= decl-type js2-CONST)
-          (= decl-type js2-FUNCTION))
-      (if symbol
-          (if (and js2-strict-var-redeclaration-warning (= sdt js2-VAR))
-              (js2-add-strict-warning "msg.var.redecl" name)
-            (if (and js2-strict-var-hides-function-arg-warning (= sdt js2-LP))
-                (js2-add-strict-warning "msg.var.hides.arg" name)))
-        (js2-define-new-symbol decl-type name node)))
-
-     ((= decl-type js2-LP)
-      (if symbol
-          ;; must be duplicate parameter. Second parameter hides the
-          ;; first, so go ahead and add the second pararameter
-          (js2-report-warning "msg.dup.parms" name))
-      (js2-define-new-symbol decl-type name node))
-
-     (t (js2-code-bug)))))
-
-(defun js2-parse-expr ()
-  (let* ((pn (js2-parse-assign-expr))
-         (pos (js2-node-pos pn))
-         left
-         right
-         op-pos)
-    (while (js2-match-token js2-COMMA)
-      (setq op-pos (- js2-token-beg pos))  ; relative
-      (if (= (js2-peek-token) js2-YIELD)
-          (js2-report-error "msg.yield.parenthesized"))
-      (setq right (js2-parse-assign-expr)
-            left pn
-            pn (make-js2-infix-node :type js2-COMMA
-                                    :pos pos
-                                    :len (- js2-ts-cursor pos)
-                                    :op-pos op-pos
-                                    :left left
-                                    :right right))
-      (js2-node-add-children pn left right))
-    pn))
-
-(defun js2-parse-assign-expr ()
-  (let ((tt (js2-peek-token))
-        (pos js2-token-beg)
-        pn
-        left
-        right
-        op-pos)
-    (if (= tt js2-YIELD)
-        (js2-parse-return-or-yield tt t)
-      ;; not yield - parse assignment expression
-      (setq pn (js2-parse-cond-expr)
-            tt (js2-peek-token))
-      (when (and (<= js2-first-assign tt)
-                 (<= tt js2-last-assign))
-        (js2-consume-token)
-        (setq op-pos (- js2-token-beg pos)  ; relative
-              left pn
-              right (js2-parse-assign-expr)
-              pn (make-js2-assign-node :type tt
-                                       :pos pos
-                                       :len (- (js2-node-end right) pos)
-                                       :op-pos op-pos
-                                       :left left
-                                       :right right))
-        (when js2-parse-ide-mode
-          (js2-highlight-assign-targets pn left right)
-          (if (or (js2-function-node-p right)
-                  (js2-object-node-p right))
-              (js2-record-imenu-functions right left)))
-        ;; do this last so ide checks above can use absolute positions
-        (js2-node-add-children pn left right))
-      pn)))
-
-(defun js2-parse-cond-expr ()
-  (let ((pos js2-token-beg)
-        (pn (js2-parse-or-expr))
-        test-expr
-        if-true
-        if-false
-        q-pos
-        c-pos)
-    (when (js2-match-token js2-HOOK)
-      (setq q-pos (- js2-token-beg pos)
-            if-true (js2-parse-assign-expr))
-      (js2-must-match js2-COLON "msg.no.colon.cond")
-      (setq c-pos (- js2-token-beg pos)
-            if-false (js2-parse-assign-expr)
-            test-expr pn
-            pn (make-js2-cond-node :pos pos
-                                   :len (- (js2-node-end if-false) pos)
-                                   :test-expr test-expr
-                                   :true-expr if-true
-                                   :false-expr if-false
-                                   :q-pos q-pos
-                                   :c-pos c-pos))
-      (js2-node-add-children pn test-expr if-true if-false))
-    pn))
-
-(defun js2-make-binary (type left parser)
-  "Helper for constructing a binary-operator AST node.
-LEFT is the left-side-expression, already parsed, and the
-binary operator should have just been matched.
-PARSER is a function to call to parse the right operand,
-or a `js2-node' struct if it has already been parsed."
-  (let* ((pos (js2-node-pos left))
-         (op-pos (- js2-token-beg pos))
-         (right (if (js2-node-p parser)
-                    parser
-                  (funcall parser)))
-         (pn (make-js2-infix-node :type type
-                                  :pos pos
-                                  :len (- (js2-node-end right) pos)
-                                  :op-pos op-pos
-                                  :left left
-                                  :right right)))
-    (js2-node-add-children pn left right)
-    pn))
-
-(defun js2-parse-or-expr ()
-  (let ((pn (js2-parse-and-expr)))
-    (when (js2-match-token js2-OR)
-      (setq pn (js2-make-binary js2-OR
-                                pn
-                                'js2-parse-or-expr)))
-    pn))
-
-(defun js2-parse-and-expr ()
-  (let ((pn (js2-parse-bit-or-expr)))
-    (when (js2-match-token js2-AND)
-      (setq pn (js2-make-binary js2-AND
-                                pn
-                                'js2-parse-and-expr)))
-    pn))
-
-(defun js2-parse-bit-or-expr ()
-  (let ((pn (js2-parse-bit-xor-expr)))
-    (while (js2-match-token js2-BITOR)
-      (setq pn (js2-make-binary js2-BITOR
-                                pn
-                                'js2-parse-bit-xor-expr)))
-    pn))
-
-(defun js2-parse-bit-xor-expr ()
-  (let ((pn (js2-parse-bit-and-expr)))
-    (while (js2-match-token js2-BITXOR)
-      (setq pn (js2-make-binary js2-BITXOR
-                                pn
-                                'js2-parse-bit-and-expr)))
-    pn))
-
-(defun js2-parse-bit-and-expr ()
-  (let ((pn (js2-parse-eq-expr)))
-    (while (js2-match-token js2-BITAND)
-      (setq pn (js2-make-binary js2-BITAND
-                                pn
-                                'js2-parse-eq-expr)))
-    pn))
-
-(defconst js2-parse-eq-ops
-  (list js2-EQ js2-NE js2-SHEQ js2-SHNE))
-
-(defun js2-parse-eq-expr ()
-  (let ((pn (js2-parse-rel-expr))
-        tt)
-    (while (memq (setq tt (js2-peek-token)) js2-parse-eq-ops)
-      (js2-consume-token)
-      (setq pn (js2-make-binary tt
-                                pn
-                                'js2-parse-rel-expr)))
-    pn))
-
-(defconst js2-parse-rel-ops
-  (list js2-IN js2-INSTANCEOF js2-LE js2-LT js2-GE js2-GT))
-
-(defun js2-parse-rel-expr ()
-  (let ((pn (js2-parse-shift-expr))
-        (continue t)
-        tt)
-    (while continue
-      (setq tt (js2-peek-token))
-      (cond
-       ((and js2-in-for-init (= tt js2-IN))
-        (setq continue nil))
-       ((memq tt js2-parse-rel-ops)
-        (js2-consume-token)
-        (setq pn (js2-make-binary tt pn 'js2-parse-shift-expr)))
-       (t
-        (setq continue nil))))
-    pn))
-
-(defconst js2-parse-shift-ops
-  (list js2-LSH js2-URSH js2-RSH))
-
-(defun js2-parse-shift-expr ()
-  (let ((pn (js2-parse-add-expr))
-        tt
-        (continue t))
-    (while continue
-      (setq tt (js2-peek-token))
-      (if (memq tt js2-parse-shift-ops)
-          (progn
-            (js2-consume-token)
-            (setq pn (js2-make-binary tt pn 'js2-parse-add-expr)))
-        (setq continue nil)))
-    pn))
-
-(defun js2-parse-add-expr ()
-  (let ((pn (js2-parse-mul-expr))
-        tt
-        (continue t))
-    (while continue
-      (setq tt (js2-peek-token))
-      (if (or (= tt js2-ADD) (= tt js2-SUB))
-          (progn
-            (js2-consume-token)
-            (setq pn (js2-make-binary tt pn 'js2-parse-mul-expr)))
-        (setq continue nil)))
-    pn))
-
-(defconst js2-parse-mul-ops
-  (list js2-MUL js2-DIV js2-MOD))
-
-(defun js2-parse-mul-expr ()
-  (let ((pn (js2-parse-unary-expr))
-        tt
-        (continue t))
-    (while continue
-      (setq tt (js2-peek-token))
-      (if (memq tt js2-parse-mul-ops)
-          (progn
-            (js2-consume-token)
-            (setq pn (js2-make-binary tt pn 'js2-parse-unary-expr)))
-        (setq continue nil)))
-    pn))
-
-(defsubst js2-make-unary (type parser &rest args)
-  "Make a unary node of type TYPE.
-PARSER is either a node (for postfix operators) or a function to call
-to parse the operand (for prefix operators)."
-  (let* ((pos js2-token-beg)
-         (postfix (js2-node-p parser))
-         (expr (if postfix
-                   parser
-                 (apply parser args)))
-         end
-         pn)
-    (if postfix  ; e.g. i++
-        (setq pos (js2-node-pos expr)
-              end js2-token-end)
-      (setq end (js2-node-end expr)))
-    (setq pn (make-js2-unary-node :type type
-                                  :pos pos
-                                  :len (- end pos)
-                                  :operand expr))
-    (js2-node-add-children pn expr)
-    pn))
-
-(defconst js2-incrementable-node-types
-  (list js2-NAME js2-GETPROP js2-GETELEM js2-GET_REF js2-CALL)
-  "Node types that can be the operand of a ++ or -- operator.")
-
-(defsubst js2-check-bad-inc-dec (tt beg end unary)
-  (unless (memq (js2-node-type (js2-unary-node-operand unary))
-                js2-incrementable-node-types)
-    (js2-report-error (if (= tt js2-INC)
-                          "msg.bad.incr"
-                        "msg.bad.decr")
-                      nil beg (- end beg))))
-
-(defun js2-parse-unary-expr ()
-  (let ((tt (js2-peek-token))
-        pn expr beg end)
-    (cond
-     ((or (= tt js2-VOID)
-          (= tt js2-NOT)
-          (= tt js2-BITNOT)
-          (= tt js2-TYPEOF))
-      (js2-consume-token)
-      (js2-make-unary tt 'js2-parse-unary-expr))
-
-     ((= tt js2-ADD)
-      (js2-consume-token)
-      ;; Convert to special POS token in decompiler and parse tree
-      (js2-make-unary js2-POS 'js2-parse-unary-expr))
-
-     ((= tt js2-SUB)
-      (js2-consume-token)
-      ;; Convert to special NEG token in decompiler and parse tree
-      (js2-make-unary js2-NEG 'js2-parse-unary-expr))
-
-     ((or (= tt js2-INC)
-          (= tt js2-DEC))
-      (js2-consume-token)
-      (prog1
-          (setq beg js2-token-beg
-                end js2-token-end
-                expr (js2-make-unary tt 'js2-parse-member-expr t))
-        (js2-check-bad-inc-dec tt beg end expr)))
-
-     ((= tt js2-DELPROP)
-      (js2-consume-token)
-      (js2-make-unary js2-DELPROP 'js2-parse-unary-expr))
-
-     ((= tt js2-ERROR)
-      (js2-consume-token)
-      (make-js2-error-node))  ; try to continue
-
-     ((and (= tt js2-LT)
-           js2-compiler-xml-available)
-      ;; XML stream encountered in expression.
-      (js2-consume-token)
-      (js2-parse-member-expr-tail t (js2-parse-xml-initializer)))
-     (t
-      (setq pn (js2-parse-member-expr t)
-            ;; Don't look across a newline boundary for a postfix incop.
-            tt (js2-peek-token-or-eol))
-      (when (or (= tt js2-INC) (= tt js2-DEC))
-        (js2-consume-token)
-        (setf expr pn
-              pn (js2-make-unary tt expr))
-        (js2-node-set-prop pn 'postfix t)
-        (js2-check-bad-inc-dec tt js2-token-beg js2-token-end pn))
-      pn))))
-
-(defun js2-parse-xml-initializer ()
-  "Parse an E4X XML initializer.
-I'm parsing it the way Rhino parses it, but without the tree-rewriting.
-Then I'll postprocess the result, depending on whether we're in IDE
-mode or codegen mode, and generate the appropriate rewritten AST.
-IDE mode uses a rich AST that models the XML structure.  Codegen mode
-just concatenates everything and makes a new XML or XMLList out of it."
-  (let ((tt (js2-get-first-xml-token))
-        pn-xml
-        pn
-        expr
-        kids
-        expr-pos
-        (continue t)
-        (first-token t))
-    (when (not (or (= tt js2-XML) (= tt js2-XMLEND)))
-      (js2-report-error "msg.syntax"))
-    (setq pn-xml (make-js2-xml-node))
-    (while continue
-      (if first-token
-          (setq first-token nil)
-        (setq tt (js2-get-next-xml-token)))
-      (cond
-       ;; js2-XML means we found a {expr} in the XML stream.
-       ;; The js2-ts-string is the XML up to the left-curly.
-       ((= tt js2-XML)
-        (push (make-js2-string-node :pos js2-token-beg
-                                    :len (- js2-ts-cursor js2-token-beg))
-              kids)
-        (js2-must-match js2-LC "msg.syntax")
-        (setq expr-pos js2-ts-cursor
-              expr (if (eq (js2-peek-token) js2-RC)
-                       (make-js2-empty-expr-node :pos expr-pos)
-                     (js2-parse-expr)))
-        (js2-must-match js2-RC "msg.syntax")
-        (setq pn (make-js2-xml-js-expr-node :pos (js2-node-pos expr)
-                                            :len (js2-node-len expr)
-                                            :expr expr))
-        (js2-node-add-children pn expr)
-        (push pn kids))
-
-       ;; a js2-XMLEND token means we hit the final close-tag.
-       ((= tt js2-XMLEND)
-        (push (make-js2-string-node :pos js2-token-beg
-                                    :len (- js2-ts-cursor js2-token-beg))
-              kids)
-        (dolist (kid (nreverse kids))
-          (js2-block-node-push pn-xml kid))
-        (setf (js2-node-len pn-xml) (- js2-ts-cursor
-                                       (js2-node-pos pn-xml))
-              continue nil))
-       (t
-        (js2-report-error "msg.syntax")
-        (setq continue nil))))
-    pn-xml))
-
-
-(defun js2-parse-argument-list ()
-  "Parse an argument list and return it as a lisp list of nodes.
-Returns the list in reverse order.  Consumes the right-paren token."
-  (let (result)
-    (unless (js2-match-token js2-RP)
-      (loop do
-            (if (= (js2-peek-token) js2-YIELD)
-                (js2-report-error "msg.yield.parenthesized"))
-            (push (js2-parse-assign-expr) result)
-            while
-            (js2-match-token js2-COMMA))
-      (js2-must-match js2-RP "msg.no.paren.arg")
-      result)))
-
-(defun js2-parse-member-expr (&optional allow-call-syntax)
-  (let ((tt (js2-peek-token))
-        pn
-        pos
-        target
-        args
-        beg
-        end
-        init
-        tail)
-    (if (/= tt js2-NEW)
-        (setq pn (js2-parse-primary-expr))
-      ;; parse a 'new' expression
-      (js2-consume-token)
-      (setq pos js2-token-beg
-            beg pos
-            target (js2-parse-member-expr)
-            end (js2-node-end target)
-            pn (make-js2-new-node :pos pos
-                                  :target target
-                                  :len (- end pos)))
-      (js2-node-add-children pn target)
-      (when (js2-match-token js2-LP)
-        ;; Add the arguments to pn, if any are supplied.
-        (setf beg pos  ; start of "new" keyword
-              pos js2-token-beg
-              args (nreverse (js2-parse-argument-list))
-              (js2-new-node-args pn) args
-              end js2-token-end
-              (js2-new-node-lp pn) (- pos beg)
-              (js2-new-node-rp pn) (- end 1 beg))
-        (apply #'js2-node-add-children pn args))
-
-      (when (and js2-allow-rhino-new-expr-initializer
-                 (js2-match-token js2-LC))
-        (setf init (js2-parse-object-literal)
-              end (js2-node-end init)
-              (js2-new-node-initializer pn) init)
-        (js2-node-add-children pn init))
-
-        (setf (js2-node-len pn) (- beg pos)))  ; end outer if
-
-    (js2-parse-member-expr-tail allow-call-syntax pn)))
-
-(defun js2-parse-member-expr-tail (allow-call-syntax pn)
-  "Parse a chain of property/array accesses or function calls.
-Includes parsing for E4X operators like `..' and `.@'.
-If ALLOW-CALL-SYNTAX is nil, stops when we encounter a left-paren.
-Returns an expression tree that includes PN, the parent node."
-  (let ((beg (js2-node-pos pn))
-        tt
-        (continue t))
-    (while continue
-      (setq tt (js2-peek-token))
-      (cond
-       ((or (= tt js2-DOT) (= tt js2-DOTDOT))
-        (setq pn (js2-parse-property-access tt pn)))
-
-       ((= tt js2-DOTQUERY)
-        (setq pn (js2-parse-dot-query pn)))
-
-       ((= tt js2-LB)
-        (setq pn (js2-parse-element-get pn)))
-
-       ((= tt js2-LP)
-        (if allow-call-syntax
-            (setq pn (js2-parse-function-call pn))
-          (setq continue nil)))
-       (t
-        (setq continue nil))))
-    (if (>= js2-highlight-level 2)
-        (js2-parse-highlight-member-expr-node pn))
-    pn))
-
-(defun js2-parse-dot-query (pn)
-  "Parse a dot-query expression, e.g. foo.bar.(@name == 2)
-Last token parsed must be `js2-DOTQUERY'."
-  (let ((pos (js2-node-pos pn))
-        op-pos
-        expr
-        end)
-    (js2-consume-token)
-    (js2-must-have-xml)
-    (js2-set-requires-activation)
-    (setq op-pos js2-token-beg
-          expr (js2-parse-expr)
-          end (js2-node-end expr)
-          pn (make-js2-xml-dot-query-node :left pn
-                                          :pos pos
-                                          :op-pos op-pos
-                                          :right expr))
-    (js2-node-add-children pn
-                           (js2-xml-dot-query-node-left pn)
-                           (js2-xml-dot-query-node-right pn))
-    (if (js2-must-match js2-RP "msg.no.paren")
-        (setf (js2-xml-dot-query-node-rp pn) js2-token-beg
-              end js2-token-end))
-    (setf (js2-node-len pn) (- end pos))
-    pn))
-
-(defun js2-parse-element-get (pn)
-  "Parse an element-get expression, e.g. foo[bar].
-Last token parsed must be `js2-RB'."
-  (let ((lb js2-token-beg)
-        (pos (js2-node-pos pn))
-        rb
-        expr)
-    (js2-consume-token)
-    (setq expr (js2-parse-expr))
-    (if (js2-must-match js2-RB "msg.no.bracket.index")
-        (setq rb js2-token-beg))
-    (setq pn (make-js2-elem-get-node :target pn
-                                     :pos pos
-                                     :element expr
-                                     :lb (js2-relpos lb pos)
-                                     :rb (js2-relpos rb pos)
-                                     :len (- js2-token-end pos)))
-    (js2-node-add-children pn
-                           (js2-elem-get-node-target pn)
-                           (js2-elem-get-node-element pn))
-    pn))
-
-(defun js2-parse-function-call (pn)
-  (let (args
-        (pos (js2-node-pos pn)))
-    (js2-consume-token)
-    (setq pn (make-js2-call-node :pos pos
-                                 :target pn
-                                 :lp (- js2-token-beg pos)))
-    (js2-node-add-children pn (js2-call-node-target pn))
-
-    ;; Add the arguments to pn, if any are supplied.
-    (setf args (nreverse (js2-parse-argument-list))
-          (js2-call-node-rp pn) (- js2-token-beg pos)
-          (js2-call-node-args pn) args)
-    (apply #'js2-node-add-children pn args)
-
-    (setf (js2-node-len pn) (- js2-ts-cursor pos))
-    pn))
-
-(defun js2-parse-property-access (tt pn)
-  "Parse a property access, XML descendants access, or XML attr access."
-  (let ((member-type-flags 0)
-        (dot-pos js2-token-beg)
-        (dot-len (if (= tt js2-DOTDOT) 2 1))
-        name
-        ref  ; right side of . or .. operator
-        result)
-    (js2-consume-token)
-    (when (= tt js2-DOTDOT)
-      (js2-must-have-xml)
-      (setq member-type-flags js2-descendants-flag))
-    (if (not js2-compiler-xml-available)
-        (progn
-          (js2-must-match-prop-name "msg.no.name.after.dot")
-          (setq name (js2-create-name-node t js2-GETPROP)
-                result (make-js2-prop-get-node :left pn
-                                               :pos js2-token-beg
-                                               :right name
-                                               :len (- js2-token-end
-                                                       js2-token-beg)))
-          (js2-node-add-children result pn name)
-          result)
-      ;; otherwise look for XML operators
-      (setf result (if (= tt js2-DOT)
-                       (make-js2-prop-get-node)
-                     (make-js2-infix-node :type js2-DOTDOT))
-            (js2-node-pos result) (js2-node-pos pn)
-            (js2-infix-node-op-pos result) dot-pos
-            (js2-infix-node-left result) pn  ; do this after setting position
-            tt (js2-next-token))
-      (cond
-       ;; needed for generator.throw()
-       ((= tt js2-THROW)
-        (js2-save-name-token-data js2-token-beg "throw")
-        (setq ref (js2-parse-property-name nil js2-ts-string member-type-flags)))
-
-       ;; handles: name, ns::name, ns::*, ns::[expr]
-       ((js2-valid-prop-name-token tt)
-        (setq ref (js2-parse-property-name -1 js2-ts-string member-type-flags)))
-
-       ;; handles: *, *::name, *::*, *::[expr]
-       ((= tt js2-MUL)
-        (js2-save-name-token-data js2-token-beg "*")
-        (setq ref (js2-parse-property-name nil "*" member-type-flags)))
-
-       ;; handles: '@attr', '@ns::attr', '@ns::*', '@ns::[expr]', etc.
-       ((= tt js2-XMLATTR)
-        (setq result (js2-parse-attribute-access)))
-
-       (t
-        (js2-report-error "msg.no.name.after.dot" nil dot-pos dot-len)))
-
-      (if ref
-          (setf (js2-node-len result) (- (js2-node-end ref)
-                                         (js2-node-pos result))
-                (js2-infix-node-right result) ref))
-      (if (js2-infix-node-p result)
-          (js2-node-add-children result
-                                 (js2-infix-node-left result)
-                                 (js2-infix-node-right result)))
-      result)))
-
-(defun js2-parse-attribute-access ()
-  "Parse an E4X XML attribute expression.
-This includes expressions of the forms:
-
-  @attr      @ns::attr     @ns::*
-  @*         @*::attr      @*::*
-  @[expr]    @*::[expr]    @ns::[expr]
-
-Called if we peeked an '@' token."
-  (let ((tt (js2-next-token))
-        (at-pos js2-token-beg))
-    (cond
-     ;; handles: @name, @ns::name, @ns::*, @ns::[expr]
-     ((js2-valid-prop-name-token tt)
-      (js2-parse-property-name at-pos js2-ts-string 0))
-
-     ;; handles: @*, @*::name, @*::*, @*::[expr]
-     ((= tt js2-MUL)
-      (js2-save-name-token-data js2-token-beg "*")
-      (js2-parse-property-name js2-token-beg "*" 0))
-
-     ;; handles @[expr]
-     ((= tt js2-LB)
-      (js2-parse-xml-elem-ref at-pos))
-
-     (t
-      (js2-report-error "msg.no.name.after.xmlAttr")
-      ;; Avoid cascaded errors that happen if we make an error node here.
-      (js2-save-name-token-data js2-token-beg "")
-      (js2-parse-property-name js2-token-beg "" 0)))))
-
-(defun js2-parse-property-name (at-pos s member-type-flags)
-  "Check if :: follows name in which case it becomes qualified name.
-
-AT-POS is a natural number if we just read an '@' token, else nil.
-S is the name or string that was matched:  an identifier, 'throw' or '*'.
-MEMBER-TYPE-FLAGS is a bit set tracking whether we're a '.' or '..' child.
-
-Returns a `js2-xml-ref-node' if it's an attribute access, a child of a '..'
-operator, or the name is followed by ::.  For a plain name, returns a
-`js2-name-node'.  Returns a `js2-error-node' for malformed XML expressions."
-  (let ((pos (or at-pos js2-token-beg))
-        colon-pos
-        (name (js2-create-name-node t js2-current-token))
-        ns
-        tt
-        ref
-        pn)
-    (catch 'return
-      (when (js2-match-token js2-COLONCOLON)
-        (setq ns name
-              colon-pos js2-token-beg
-              tt (js2-next-token))
-        (cond
-         ;; handles name::name
-         ((js2-valid-prop-name-token tt)
-          (setq name (js2-create-name-node)))
-
-         ;; handles name::*
-         ((= tt js2-MUL)
-          (js2-save-name-token-data js2-token-beg "*")
-          (setq name (js2-create-name-node)))
-
-         ;; handles name::[expr]
-         ((= tt js2-LB)
-          (throw 'return (js2-parse-xml-elem-ref at-pos ns colon-pos)))
-
-         (t
-          (js2-report-error "msg.no.name.after.coloncolon"))))
-
-      (if (and (null ns) (zerop member-type-flags))
-          name
-        (prog1
-            (setq pn
-                  (make-js2-xml-prop-ref-node :pos pos
-                                              :len (- (js2-node-end name) pos)
-                                              :at-pos at-pos
-                                              :colon-pos colon-pos
-                                              :propname name))
-          (js2-node-add-children pn name))))))
-
-(defun js2-parse-xml-elem-ref (at-pos &optional namespace colon-pos)
-  "Parse the [expr] portion of an xml element reference.
-For instance, @[expr], @*::[expr], or ns::[expr]."
-  (let* ((lb js2-token-beg)
-         (pos (or at-pos lb))
-         rb
-         (expr (js2-parse-expr))
-         (end (js2-node-end expr))
-         pn)
-    (if (js2-must-match js2-RB "msg.no.bracket.index")
-        (setq rb js2-token-beg
-              end js2-token-end))
-    (prog1
-        (setq pn
-              (make-js2-xml-elem-ref-node :pos pos
-                                          :len (- end pos)
-                                          :namespace namespace
-                                          :colon-pos colon-pos
-                                          :at-pos at-pos
-                                          :expr expr
-                                          :lb (js2-relpos lb pos)
-                                          :rb (js2-relpos rb pos)))
-      (js2-node-add-children pn namespace expr))))
-
-(defun js2-parse-primary-expr ()
-  "Parses a literal (leaf) expression of some sort.
-Includes complex literals such as functions, object-literals,
-array-literals, array comprehensions and regular expressions."
-  (let ((tt-flagged (js2-next-flagged-token))
-        pn      ; parent node  (usually return value)
-        tt
-        px-pos  ; paren-expr pos
-        len
-        flags   ; regexp flags
-        expr)
-    (setq tt js2-current-token)
-    (cond
-     ((= tt js2-FUNCTION)
-      (js2-parse-function 'FUNCTION_EXPRESSION))
-
-     ((= tt js2-LB)
-      (js2-parse-array-literal))
-
-     ((= tt js2-LC)
-      (js2-parse-object-literal))
-
-     ((= tt js2-LET)
-      (js2-parse-let js2-token-beg))
-
-     ((= tt js2-LP)
-      (setq px-pos js2-token-beg
-            expr (js2-parse-expr))
-      (js2-must-match js2-RP "msg.no.paren")
-      (setq pn (make-js2-paren-node :pos px-pos
-                                    :expr expr
-                                    :len (- js2-token-end px-pos)))
-      (js2-node-add-children pn (js2-paren-node-expr pn))
-      pn)
-
-     ((= tt js2-XMLATTR)
-      (js2-must-have-xml)
-      (js2-parse-attribute-access))
-
-     ((= tt js2-NAME)
-      (js2-parse-name tt-flagged tt))
-
-     ((= tt js2-NUMBER)
-      (make-js2-number-node))
-
-     ((= tt js2-STRING)
-      (prog1
-          (make-js2-string-node)
-        (js2-record-face 'font-lock-string-face)))
-
-     ((or (= tt js2-DIV) (= tt js2-ASSIGN_DIV))
-      ;; Got / or /= which in this context means a regexp literal
-      (setq px-pos js2-token-beg)
-      (js2-read-regexp tt)
-      (setq flags js2-ts-regexp-flags
-            js2-ts-regexp-flags nil)
-      (prog1
-          (make-js2-regexp-node :pos px-pos
-                                :len (- js2-ts-cursor px-pos)
-                                :value js2-ts-string
-                                :flags flags)
-        (js2-set-face px-pos js2-ts-cursor 'font-lock-string-face 'record)))
-
-     ((or (= tt js2-NULL)
-          (= tt js2-THIS)
-          (= tt js2-FALSE)
-          (= tt js2-TRUE))
-      (make-js2-keyword-node :type tt))
-
-     ((= tt js2-RESERVED)
-      (js2-report-error "msg.reserved.id")
-      (make-js2-name-node))
-
-     ((= tt js2-ERROR)
-      ;; the scanner or one of its subroutines reported the error.
-      (make-js2-error-node))
-
-     ((= tt js2-EOF)
-      (setq px-pos (point-at-bol)
-            len (- js2-ts-cursor px-pos))
-      (js2-report-error "msg.unexpected.eof" nil px-pos len)
-      (make-js2-error-node :pos px-pos :len len))
-
-     (t
-      (js2-report-error "msg.syntax")
-      (make-js2-error-node)))))
-
-(defun js2-parse-name (tt-flagged tt)
-  (let ((name js2-ts-string)
-        (name-pos js2-token-beg))
-      (if (and (js2-flag-set-p tt-flagged js2-ti-check-label)
-               (= (js2-peek-token) js2-COLON))
-          (prog1
-            ;; Do not consume colon, it is used as unwind indicator
-            ;; to return to statementHelper.
-            (make-js2-label-node :pos name-pos
-                                 :len (- js2-token-end name-pos)
-                                 :name name)
-            (js2-set-face name-pos
-                          js2-token-end
-                          'font-lock-variable-name-face 'record))
-        ;; Otherwise not a label, just a name.  Unfortunately peeking
-        ;; the next token to check for a colon has biffed js2-token-beg
-        ;; and js2-token-end.  We store the name's bounds in buffer vars
-        ;; and `js2-create-name-node' uses them.
-        (js2-save-name-token-data name-pos name)
-        (if js2-compiler-xml-available
-            (js2-parse-property-name nil name 0)
-          (js2-create-name-node 'check-activation)))))
-
-(defsubst js2-parse-warn-trailing-comma (msg pos elems comma-pos)
-  (js2-add-strict-warning
-   msg nil
-   ;; back up from comma to beginning of line or array/objlit
-   (max (if elems
-            (js2-node-pos (car elems))
-          pos)
-        (save-excursion
-          (goto-char comma-pos)
-          (back-to-indentation)
-          (point)))
-   comma-pos))
-
-(defun js2-parse-array-literal ()
-  (let ((pos js2-token-beg)
-        (end js2-token-end)
-        (after-lb-or-comma t)
-        after-comma
-        tt
-        elems
-        pn
-        (continue t))
-    (while continue
-      (setq tt (js2-peek-token))
-      (cond
-       ;; comma
-       ((= tt js2-COMMA)
-        (js2-consume-token)
-        (setq after-comma js2-token-end)
-        (if (not after-lb-or-comma)
-            (setq after-lb-or-comma t)
-          (push nil elems)))
-
-       ;; end of array
-       ((or (= tt js2-RB)
-            (= tt js2-EOF))  ; prevent infinite loop
-        (if (= tt js2-EOF)
-            (js2-report-error "msg.no.bracket.arg" nil pos)
-          (js2-consume-token))
-        (setq continue nil
-              end js2-token-end
-              pn (make-js2-array-node :pos pos
-                                      :len (- js2-ts-cursor pos)
-                                      :elems (nreverse elems)))
-        (apply #'js2-node-add-children pn (js2-array-node-elems pn))
-        (when after-comma
-          (js2-parse-warn-trailing-comma "msg.array.trailing.comma"
-                                         pos elems after-comma)))
-
-       ;; array comp
-       ((and (>= js2-language-version 170)
-             (= tt js2-FOR)          ; check for array comprehension
-             (not after-lb-or-comma) ; "for" can't follow a comma
-             elems                   ; must have at least 1 element
-             (not (cdr elems)))      ; but no 2nd element
-        (setf continue nil
-              pn (js2-parse-array-comprehension (car elems) pos)))
-
-       ;; another element
-       (t
-        (unless after-lb-or-comma
-          (js2-report-error "msg.no.bracket.arg"))
-        (push (js2-parse-assign-expr) elems)
-        (setq after-lb-or-comma nil
-              after-comma nil))))
-    pn))
-
-(defun js2-parse-array-comprehension (expr pos)
-  "Parse a JavaScript 1.7 Array Comprehension.
-EXPR is the first expression after the opening left-bracket.
-POS is the beginning of the LB token preceding EXPR.
-We should have just parsed the 'for' keyword before calling this function."
-  (let (loops
-        filter
-        if-pos
-        result)
-    (while (= (js2-peek-token) js2-FOR)
-      (push (js2-parse-array-comp-loop) loops))
-    (when (= (js2-peek-token) js2-IF)
-      (js2-consume-token)
-      (setq if-pos (- js2-token-beg pos)  ; relative
-            filter (js2-parse-condition)))
-    (js2-must-match js2-RB "msg.no.bracket.arg" pos)
-    (setq result (make-js2-array-comp-node :pos pos
-                                           :len (- js2-ts-cursor pos)
-                                           :result expr
-                                           :loops (nreverse loops)
-                                           :filter (car filter)
-                                           :lp (js2-relpos (second filter) pos)
-                                           :rp (js2-relpos (third filter) pos)
-                                           :if-pos if-pos))
-    (apply #'js2-node-add-children result expr (car filter)
-           (js2-array-comp-node-loops result))
-    result))
-
-(defun js2-parse-array-comp-loop ()
-  "Parse a 'for [each] (foo in bar)' expression in an Array comprehension.
-Last token peeked should be the initial FOR."
-  (let ((pos js2-token-beg)
-        (pn (make-js2-array-comp-loop-node))
-        tt
-        iter
-        obj
-        foreach-p
-        in-pos
-        each-pos
-        lp
-        rp)
-    (assert (= (js2-next-token) js2-FOR))  ; consumes token
-    (js2-push-scope pn)
-    (unwind-protect
-        (progn
-          (when (js2-match-token js2-NAME)
-            (if (string= js2-ts-string "each")
-                (progn
-                  (setq foreach-p t
-                        each-pos (- js2-token-beg pos)) ; relative
-                  (js2-record-face 'font-lock-keyword-face))
-              (js2-report-error "msg.no.paren.for")))
-
-          (if (js2-must-match js2-LP "msg.no.paren.for")
-              (setq lp (- js2-token-beg pos)))
-
-          (setq tt (js2-peek-token))
-          (cond
-           ((or (= tt js2-LB)
-                (= tt js2-LC))
-            ;; handle destructuring assignment
-            (setq iter (js2-parse-primary-expr)))
-
-           ((js2-valid-prop-name-token tt)
-            (js2-consume-token)
-            (setq iter (js2-create-name-node)))
-
-           (t
-            (js2-report-error "msg.bad.var")))
-
-          ;; Define as a let since we want the scope of the variable to
-          ;; be restricted to the array comprehension
-          (if (js2-name-node-p iter)
-              (js2-define-symbol js2-LET (js2-name-node-name iter) pn t))
-
-          (if (js2-must-match js2-IN "msg.in.after.for.name")
-              (setq in-pos (- js2-token-beg pos)))
-
-          (setq obj (js2-parse-expr))
-          (if (js2-must-match js2-RP "msg.no.paren.for.ctrl")
-              (setq rp (- js2-token-beg pos)))
-
-          (setf (js2-node-pos pn) pos
-                (js2-node-len pn) (- js2-ts-cursor pos)
-                (js2-array-comp-loop-node-iterator pn) iter
-                (js2-array-comp-loop-node-object pn) obj
-                (js2-array-comp-loop-node-in-pos pn) in-pos
-                (js2-array-comp-loop-node-each-pos pn) each-pos
-                (js2-array-comp-loop-node-foreach-p pn) foreach-p
-                (js2-array-comp-loop-node-lp pn) lp
-                (js2-array-comp-loop-node-rp pn) rp)
-          (js2-node-add-children pn iter obj))
-      (js2-pop-scope))
-    pn))
-
-(defun js2-parse-object-literal ()
-  (let ((pos js2-token-beg)
-        tt
-        elems
-        result
-        after-comma
-        (continue t))
-    (while continue
-      (setq tt (js2-peek-token))
-      (cond
-       ;; {foo: ...}, {'foo': ...}, {get foo() {...}}, or {set foo(x) {...}}
-       ((or (js2-valid-prop-name-token tt)
-            (= tt js2-STRING))
-        (setq after-comma nil
-              result (js2-parse-named-prop tt))
-        (if (and (null result)
-                 (not js2-recover-from-parse-errors))
-            (setq continue nil)
-          (push result elems)))
-
-       ;; {12: x} or {10.7: x}
-       ((= tt js2-NUMBER)
-        (js2-consume-token)
-        (setq after-comma nil)
-        (push (js2-parse-plain-property (make-js2-number-node)) elems))
-
-       ;; trailing comma
-       ((= tt js2-RC)
-        (setq continue nil)
-        (if after-comma
-            (js2-parse-warn-trailing-comma "msg.extra.trailing.comma"
-                                           pos elems after-comma)))
-       (t
-        (js2-report-error "msg.bad.prop")
-        (unless js2-recover-from-parse-errors
-          (setq continue nil))))         ; end switch
-
-      (if (js2-match-token js2-COMMA)
-          (setq after-comma js2-token-end)
-        (setq continue nil)))           ; end loop
-
-    (js2-must-match js2-RC "msg.no.brace.prop")
-    (setq result (make-js2-object-node :pos pos
-                                       :len (- js2-ts-cursor pos)
-                                       :elems (nreverse elems)))
-    (apply #'js2-node-add-children result (js2-object-node-elems result))
-    result))
-
-(defun js2-parse-named-prop (tt)
-  "Parse a name, string, or getter/setter object property."
-  (js2-consume-token)
-  (let ((string-prop (and (= tt js2-STRING)
-                          (make-js2-string-node)))
-        expr
-        (ppos js2-token-beg)
-        (pend js2-token-end)
-        (name (js2-create-name-node))
-        (prop js2-ts-string))
-
-    (if (and (= tt js2-NAME)
-             (= (js2-peek-token) js2-NAME)
-             (or (string= prop "get")
-                 (string= prop "set")))
-        (progn
-          ;; getter/setter prop
-          (js2-consume-token)
-          (js2-set-face ppos pend 'font-lock-keyword-face 'record)  ; get/set
-          (js2-record-face 'font-lock-function-name-face)      ; for peeked name
-          (setq name (js2-create-name-node)) ; discard get/set & use peeked name
-          (js2-parse-getter-setter-prop ppos name (string= prop "get")))
-
-      ;; regular prop
-      (prog1
-          (setq expr (js2-parse-plain-property (or string-prop name)))
-        (js2-set-face ppos pend
-                      (if (js2-function-node-p
-                           (js2-object-prop-node-right expr))
-                          'font-lock-function-name-face
-                        'font-lock-variable-name-face)
-                      'record)))))
-
-(defun js2-parse-plain-property (prop)
-  "Parse a non-getter/setter property in an object literal.
-PROP is the node representing the property:  a number, name or string."
-  (js2-must-match js2-COLON "msg.no.colon.prop")
-  (let* ((pos (js2-node-pos prop))
-        (colon (- js2-token-beg pos))
-        (expr (js2-parse-assign-expr))
-        (result (make-js2-object-prop-node
-                 :pos pos
-                 ;; don't include last consumed token in length
-                 :len (- (+ (js2-node-pos expr)
-                            (js2-node-len expr))
-                         pos)
-                 :left prop
-                 :right expr
-                 :op-pos colon)))
-    (js2-node-add-children result prop expr)
-    result))
-
-(defun js2-parse-getter-setter-prop (pos prop get-p)
-  "Parse getter or setter property in an object literal.
-JavaScript syntax is:
-
-  { get foo() {...}, set foo(x) {...} }
-
-POS is the start position of the `get' or `set' keyword.
-PROP is the `js2-name-node' representing the property name.
-GET-P is non-nil if the keyword was `get'."
-  (let ((type (if get-p js2-GET js2-SET))
-        result
-        end
-        (fn (js2-parse-function 'FUNCTION_EXPRESSION)))
-
-    ;; it has to be an anonymous function, as we already parsed the name
-    (if (/= (js2-node-type fn) js2-FUNCTION)
-        (js2-report-error "msg.bad.prop")
-      (if (plusp (length (js2-function-name fn)))
-          (js2-report-error "msg.bad.prop")))
-
-    (js2-node-set-prop fn 'GETTER_SETTER type)  ; for codegen
-    (setq end (js2-node-end fn)
-          result (make-js2-getter-setter-node :type type
-                                              :pos pos
-                                              :len (- end pos)
-                                              :left prop
-                                              :right fn))
-    (js2-node-add-children result prop fn)
-    result))
-
-(defun js2-create-name-node (&optional check-activation-p token)
-  "Create a name node using the token info from last scanned name.
-In some cases we need to either synthesize a name node, or we lost
-the name token information by peeking.  If the TOKEN parameter is
-not `js2-NAME', then we use the token info saved in instance vars."
-  (let ((beg js2-token-beg)
-        (s js2-ts-string)
-        name)
-    (when (/= js2-current-token js2-NAME)
-      (setq beg (or js2-prev-name-token-start js2-ts-cursor)
-            s js2-prev-name-token-string
-            js2-prev-name-token-start nil
-            js2-prev-name-token-string nil))
-    (setq name (make-js2-name-node :pos beg
-                                   :name s
-                                   :len (length s)))
-    (if check-activation-p
-        (js2-check-activation-name s (or token js2-NAME)))
-    name))
-
-(provide 'js2-parse)
-
-;;; js2-parse.el ends here
-;;; js2-indent.el --- indentation for js2-mode
-;;
-;; Copyright (C) 2008 Steve Yegge
-;; Author:  Steve Yegge (steve.yegge@gmail.com)
-;; Maintainer:  Steve Yegge (steve.yegge@gmail.com)
-
-;; Commentary:
-;;
-;; This indenter is based on Karl Landström's "javascript.el" indenter.
-;; Karl cleverly deduces that the desired indentation level is often a
-;; function of paren/bracket/brace nesting depth, which can be determined
-;; quickly via the built-in `parse-partial-sexp' function.  His indenter
-;; then does some equally clever checks to see if we're in the context of a
-;; substatement of a possibly braceless statement keyword such as if, while,
-;; or finally.  This approach yields pretty good results.
-;;
-;; The indenter is often "wrong", however, and needs to be overridden.
-;; The right long-term solution is probably to emulate (or modify)
-;; cc-engine, but it's thousands upon thousands of lines of code.  Even
-;; if you were to assume the accurate parse tree from `js2-parse' is
-;; present, indentation is still thousands of lines of code (I've been
-;; down that path) to handle every possible syntactic edge case, and in
-;; any case, relying on the parse tree is undesirable because parsing is
-;; slow.  So you might as well go the cc-engine approach, but it's a
-;; huge pile of work that I'm just not up for any time soon.
-;;
-;; In the meantime, the compromise solution is that we offer a
-;; "bounce indenter", configured with `js2-bounce-indent-flag', which
-;; cycles the current line indent among various likely guess points.
-;; This approach is far from perfect, but should at least make it
-;; slightly easier to move the line towards its desired indentation
-;; when manually overriding Karl's heuristic nesting guesser.
-;;
-;; I've made miscellaneous tweaks to Karl's code to handle some Ecma
-;; extensions such as `let' and Array comprehensions, and will likely
-;; make further tweaks to it, but major kudos to Karl for coming up with
-;; the initial approach, which packs a lot of punch for so little code.
-
-;;; Code:
-
-(defconst js-possibly-braceless-keyword-re
-  (regexp-opt
-   '("catch" "do" "else" "finally" "for" "if" "try" "while" "with" "let")
-   'words)
-  "Regular expression matching keywords that are optionally
-followed by an opening brace.")
-
-(defconst js-indent-operator-re
-  (concat "[-+*/%<>=&^|?:.]\\([^-+*/]\\|$\\)\\|"
-          (regexp-opt '("in" "instanceof") 'words))
-  "Regular expression matching operators that affect indentation
-of continued expressions.")
-
-;; This function has horrible results if you're typing an array
-;; such as [[1, 2], [3, 4], [5, 6]].  Bounce indenting -really- sucks
-;; in conjunction with electric-indent, so just disabling it.
-(defsubst js2-code-at-bol-p ()
-  "Return t if the first character on line is non-whitespace."
-  nil)
-;;        (not (memq (char-after (point-at-bol))
-;;                   '(? ?\t)))))
-
-(defun js2-insert-and-indent (key)
-  "Run command bound to key and indent current line. Runs the command
-bound to KEY in the global keymap and indents the current line."
-  (interactive (list (this-command-keys)))
-  (let ((cmd (lookup-key (current-global-map) key)))
-    (if (commandp cmd)
-        (call-interactively cmd)))
-  ;; don't do the electric keys inside comments or strings,
-  ;; and don't do bounce-indent with them.
-  (let ((parse-state (parse-partial-sexp (point-min) (point)))
-        (js2-bounce-indent-flag (js2-code-at-bol-p)))
-    (unless (or (nth 3 parse-state)
-                (nth 4 parse-state))
-      (indent-according-to-mode))))
-
-(defun js-re-search-forward-inner (regexp &optional bound count)
-  "Auxiliary function for `js-re-search-forward'."
-  (let ((parse)
-        (saved-point (point-min)))
-    (while (> count 0)
-      (re-search-forward regexp bound)
-      (setq parse (parse-partial-sexp saved-point (point)))
-      (cond ((nth 3 parse)
-             (re-search-forward
-              (concat "\\([^\\]\\|^\\)" (string (nth 3 parse)))
-              (save-excursion (end-of-line) (point)) t))
-            ((nth 7 parse)
-             (forward-line))
-            ((or (nth 4 parse)
-                 (and (eq (char-before) ?\/) (eq (char-after) ?\*)))
-             (re-search-forward "\\*/"))
-            (t
-             (setq count (1- count))))
-      (setq saved-point (point))))
-  (point))
-
-(defun js-re-search-forward (regexp &optional bound noerror count)
-  "Search forward but ignore strings and comments. Invokes
-`re-search-forward' but treats the buffer as if strings and
-comments have been removed."
-  (let ((saved-point (point))
-        (search-expr
-         (cond ((null count)
-                '(js-re-search-forward-inner regexp bound 1))
-               ((< count 0)
-                '(js-re-search-backward-inner regexp bound (- count)))
-               ((> count 0)
-                '(js-re-search-forward-inner regexp bound count)))))
-    (condition-case err
-        (eval search-expr)
-      (search-failed
-       (goto-char saved-point)
-       (unless noerror
-         (error (error-message-string err)))))))
-
-(defun js-re-search-backward-inner (regexp &optional bound count)
-  "Auxiliary function for `js-re-search-backward'."
-  (let ((parse)
-        (saved-point (point-min)))
-    (while (> count 0)
-      (re-search-backward regexp bound)
-      (setq parse (parse-partial-sexp saved-point (point)))
-      (cond ((nth 3 parse)
-             (re-search-backward
-              (concat "\\([^\\]\\|^\\)" (string (nth 3 parse)))
-              (save-excursion (beginning-of-line) (point)) t))
-            ((nth 7 parse)
-             (goto-char (nth 8 parse)))
-            ((or (nth 4 parse)
-                 (and (eq (char-before) ?/) (eq (char-after) ?*)))
-             (re-search-backward "/\\*"))
-            (t
-             (setq count (1- count))))))
-  (point))
-
-(defun js-re-search-backward (regexp &optional bound noerror count)
-  "Search backward but ignore strings and comments. Invokes
-`re-search-backward' but treats the buffer as if strings and
-comments have been removed."
-  (let ((saved-point (point))
-        (search-expr
-         (cond ((null count)
-                '(js-re-search-backward-inner regexp bound 1))
-               ((< count 0)
-                '(js-re-search-forward-inner regexp bound (- count)))
-               ((> count 0)
-                '(js-re-search-backward-inner regexp bound count)))))
-    (condition-case err
-        (eval search-expr)
-      (search-failed
-       (goto-char saved-point)
-       (unless noerror
-         (error (error-message-string err)))))))
-
-(defun js-looking-at-operator-p ()
-  "Return non-nil if text after point is an operator (that is not
-a comma)."
-  (save-match-data
-    (and (looking-at js-indent-operator-re)
-         (or (not (looking-at ":"))
-             (save-excursion
-               (and (js-re-search-backward "[?:{]\\|\\<case\\>" nil t)
-                    (looking-at "?")))))))
-
-(defun js-continued-expression-p ()
-  "Returns non-nil if the current line continues an expression."
-  (save-excursion
-    (back-to-indentation)
-    (or (js-looking-at-operator-p)
-        (and (js-re-search-backward "\n" nil t)
-	     (progn
-	       (skip-chars-backward " \t")
-	       (backward-char)
-	       (and (js-looking-at-operator-p)
-		    (and (progn (backward-char)
-				(not (looking-at "\\*\\|++\\|--\\|/[/*]"))))))))))
-
-(defun js-end-of-do-while-loop-p ()
-  "Returns non-nil if word after point is `while' of a do-while
-statement, else returns nil. A braceless do-while statement
-spanning several lines requires that the start of the loop is
-indented to the same column as the current line."
-  (interactive)
-  (save-excursion
-    (save-match-data
-      (when (looking-at "\\s-*\\<while\\>")
-	(if (save-excursion
-	      (skip-chars-backward "[ \t\n]*}")
-	      (looking-at "[ \t\n]*}"))
-	    (save-excursion
-	      (backward-list) (backward-word 1) (looking-at "\\<do\\>"))
-	  (js-re-search-backward "\\<do\\>" (point-at-bol) t)
-	  (or (looking-at "\\<do\\>")
-	      (let ((saved-indent (current-indentation)))
-		(while (and (js-re-search-backward "^[ \t]*\\<" nil t)
-			    (/= (current-indentation) saved-indent)))
-		(and (looking-at "[ \t]*\\<do\\>")
-		     (not (js-re-search-forward
-			   "\\<while\\>" (point-at-eol) t))
-		     (= (current-indentation) saved-indent)))))))))
-
-(defun js-ctrl-statement-indentation ()
-  "Returns the proper indentation of the current line if it
-starts the body of a control statement without braces, else
-returns nil."
-  (let (forward-sexp-function)  ; temporarily unbind it
-    (save-excursion
-      (back-to-indentation)
-      (when (save-excursion
-              (and (not (js2-same-line (point-min)))
-                   (not (looking-at "{"))
-                   (js-re-search-backward "[[:graph:]]" nil t)
-                   (not (looking-at "[{([]"))
-                   (progn
-                     (forward-char)
-                     ;; scan-sexps sometimes throws an error
-                     (ignore-errors (backward-sexp))
-                     (when (looking-at "(") (backward-word 1))
-                     (and (save-excursion
-                            (skip-chars-backward " \t}" (point-at-bol))
-                            (bolp))
-                          (looking-at js-possibly-braceless-keyword-re)
-                          (not (js-end-of-do-while-loop-p))))))
-        (save-excursion
-          (goto-char (match-beginning 0))
-          (+ (current-indentation) js2-basic-offset))))))
-
-(defun js2-indent-in-array-comp (parse-status)
-  "Return non-nil if we think we're in an array comprehension.
-In particular, return the buffer position of the first `for' kwd."
-  (let ((end (point)))
-    (when (nth 1 parse-status)
-      (save-excursion
-        (goto-char (nth 1 parse-status))
-        (when (looking-at "\\[")
-          (forward-char 1)
-          (js2-forward-sws)
-          (if (looking-at "[[{]")
-              (let (forward-sexp-function) ; use lisp version
-                (forward-sexp)             ; skip destructuring form
-                (js2-forward-sws)
-                (if (and (/= (char-after) ?,) ; regular array
-                         (looking-at "for"))
-                    (match-beginning 0)))
-            ;; to skip arbitrary expressions we need the parser,
-            ;; so we'll just guess at it.
-            (if (re-search-forward "[^,]* \\(for\\) " end t)
-                (match-beginning 1))))))))
-
-(defun js2-array-comp-indentation (parse-status for-kwd)
-  (if (js2-same-line for-kwd)
-      ;; first continuation line
-      (save-excursion
-        (goto-char (nth 1 parse-status))
-        (forward-char 1)
-        (skip-chars-forward " \t")
-        (current-column))
-    (save-excursion
-      (goto-char for-kwd)
-      (current-column))))
-
-(defun js-proper-indentation (parse-status)
-  "Return the proper indentation for the current line."
-  (save-excursion
-    (back-to-indentation)
-    (let ((ctrl-stmt-indent (js-ctrl-statement-indentation))
-          (same-indent-p (looking-at "[]})]\\|\\<case\\>\\|\\<default\\>"))
-          (continued-expr-p (js-continued-expression-p))
-          (bracket (nth 1 parse-status))
-          beg)
-      (cond
-       ;; indent array comprehension continuation lines specially
-       ((and bracket
-             (not (js2-same-line bracket))
-             (setq beg (js2-indent-in-array-comp parse-status))
-             (>= (point) (save-excursion
-                           (goto-char beg)
-                           (point-at-bol)))) ; at or after first loop?
-        (js2-array-comp-indentation parse-status beg))
-
-       (ctrl-stmt-indent)
-
-       (bracket
-        (goto-char bracket)
-        (cond
-         ((looking-at "[({[][ \t]*\\(/[/*]\\|$\\)")
-          (let ((p (parse-partial-sexp (point-at-bol) (point))))
-            (when (save-excursion (skip-chars-backward " \t)")
-                                  (looking-at ")"))
-              (backward-list))
-            (if (nth 1 p)
-                (progn (goto-char (1+ (nth 1 p)))
-                       (skip-chars-forward " \t"))
-              (back-to-indentation))
-            (cond (same-indent-p
-                   (current-column))
-                  (continued-expr-p
-                   (+ (current-column) (* 2 js2-basic-offset)))
-                  (t
-                   (+ (current-column) js2-basic-offset)))))
-         (t
-          (unless same-indent-p
-            (forward-char)
-            (skip-chars-forward " \t"))
-          (current-column))))
-
-       (continued-expr-p js2-basic-offset)
-       (t 0)))))
-
-(defun js2-lineup-comment (parse-status)
-  "Indent a multi-line block comment continuation line."
-  (let* ((beg (nth 8 parse-status))
-         (first-line (js2-same-line beg))
-         (offset (save-excursion
-                   (goto-char beg)
-                   (if (looking-at "/\\*")
-                       (+ 1 (current-column))
-                     0))))
-    (unless first-line
-      (indent-line-to offset))))
-
-(defun js2-backward-sws ()
-  "Move backward through whitespace and comments."
-  (interactive)
-  (while (forward-comment -1)))
-
-(defun js2-forward-sws ()
-  "Move forward through whitespace and comments."
-  (interactive)
-  (while (forward-comment 1)))
-
-(defsubst js2-current-indent (&optional pos)
-  "Return column of indentation on current line.
-If POS is non-nil, go to that point and return indentation for that line."
-  (save-excursion
-    (if pos
-        (goto-char pos))
-    (back-to-indentation)
-    (current-column)))
-
-(defsubst js2-arglist-close ()
-  "Return non-nil if we're on a line beginning with a close-paren/brace."
-  (save-match-data
-    (save-excursion
-      (goto-char (point-at-bol))
-      (js2-forward-sws)
-      (looking-at "[])}]"))))
-
-(defsubst js2-indent-looks-like-label-p ()
-  (goto-char (point-at-bol))
-  (js2-forward-sws)
-  (looking-at (concat js2-mode-identifier-re ":")))
-
-(defun js2-indent-in-objlit-p (parse-status)
-  "Return non-nil if this looks like an object-literal entry."
-  (let ((start (nth 1 parse-status)))
-    (and
-     start
-     (save-excursion
-       (and (zerop (forward-line -1))
-            (not (< (point) start))     ; crossed a {} boundary
-            (js2-indent-looks-like-label-p)))
-     (save-excursion
-       (js2-indent-looks-like-label-p)))))
-
-;; if prev line looks like foobar({ then we're passing an object
-;; literal to a function call, and people pretty much always want to
-;; de-dent back to the previous line, so move the 'basic-offset'
-;; position to the front.
-(defsubst js2-indent-objlit-arg-p (parse-status)
-  (save-excursion
-    (back-to-indentation)
-    (js2-backward-sws)
-    (and (eq (1- (point)) (nth 1 parse-status))
-         (eq (char-before) ?{)
-         (progn
-           (forward-char -1)
-           (skip-chars-backward " \t")
-           (eq (char-before) ?\()))))
-
-(defsubst js2-indent-case-block-p ()
-  (save-excursion
-    (back-to-indentation)
-    (js2-backward-sws)
-    (goto-char (point-at-bol))
-    (skip-chars-forward " \t")
-    (save-match-data
-      (looking-at "case\\s-.+:"))))
-
-(defsubst js2-syntax-bol ()
-  "Return the point at the first non-whitespace char on the line.
-Returns `point-at-bol' if the line is empty."
-  (save-excursion
-    (beginning-of-line)
-    (skip-chars-forward " \t")
-    (point)))
-
-(defun js2-bounce-indent (normal-col parse-status)
-  "Cycle among alternate computed indentation positions.
-PARSE-STATUS is the result of `parse-partial-sexp' from the beginning
-of the buffer to the current point.  NORMAL-COL is the indentation
-column computed by the heuristic guesser based on current paren,
-bracket, brace and statement nesting."
-  (let ((cur-indent (js2-current-indent))
-        (old-buffer-undo-list buffer-undo-list)
-        ;; Emacs 21 only has `count-lines', not `line-number-at-pos'
-        (current-line (save-excursion
-                        (forward-line 0)  ; move to bol
-                        (1+ (count-lines (point-min) (point)))))
-        positions
-        pos
-        anchor
-        arglist-cont
-        same-indent
-        prev-line-col
-        basic-offset
-        computed-pos)
-    ;; temporarily don't record undo info, if user requested this
-    (if js2-mode-indent-inhibit-undo
-        (setq buffer-undo-list t))
-    (unwind-protect
-        (progn
-          ;; first likely point:  indent from beginning of previous code line
-          (push (setq basic-offset
-                      (+ (save-excursion
-                           (back-to-indentation)
-                           (js2-backward-sws)
-                           (back-to-indentation)
-                           (setq prev-line-col (current-column)))
-                         js2-basic-offset))
-                positions)
-
-          ;; second likely point:  indent from assign-expr RHS.  This
-          ;; is just a crude guess based on finding " = " on the previous
-          ;; line containing actual code.
-          (setq pos (save-excursion
-                      (save-match-data
-                        (forward-line -1)
-                        (goto-char (point-at-bol))
-                        (when (re-search-forward "\\s-+\\(=\\)\\s-+"
-                                                 (point-at-eol) t)
-                          (goto-char (match-end 1))
-                          (skip-chars-forward " \t\r\n")
-                          (current-column)))))
-          (when pos
-            (incf pos js2-basic-offset)
-            (unless (member pos positions)
-              (push pos positions)))
-
-          ;; third likely point:  same indent as previous line of code.
-          ;; Make it the first likely point if we're not on an
-          ;; arglist-close line and previous line ends in a comma, or
-          ;; both this line and prev line look like object-literal
-          ;; elements.
-          (setq pos (save-excursion
-                      (goto-char (point-at-bol))
-                      (js2-backward-sws)
-                      (back-to-indentation)
-                      (prog1
-                          (current-column)
-                        ;; while we're here, look for trailing comma
-                        (if (save-excursion
-                              (goto-char (point-at-eol))
-                              (js2-backward-sws)
-                              (eq (char-before) ?,))
-                            (setq arglist-cont (1- (point)))))))
-          (when pos
-            (if (and (or arglist-cont
-                         (js2-indent-in-objlit-p parse-status))
-                     (not (js2-arglist-close)))
-                (setq same-indent pos))
-            (unless (member pos positions)
-              (push pos positions)))
-
-          ;; fourth likely position:  first preceding code with less indentation
-          ;; than the immediately preceding code line.
-          (setq pos (save-excursion
-                      (js2-backward-sws)
-                      (back-to-indentation)
-                      (setq anchor (current-column))
-                      (while (and (zerop (forward-line -1))
-                                  (>= (progn
-                                        (back-to-indentation)
-                                        (current-column))
-                                      anchor)))
-                      (setq pos (current-column))))
-          (unless (member pos positions)
-            (push pos positions))
-
-          ;; put nesting-heuristic position first in list, sort rest
-          (setq positions (nreverse (sort positions '<)))
-          (setq positions (cons normal-col (delete normal-col positions)))
-
-          ;; comma-list continuation lines:  prev line indent takes precedence
-          (if same-indent
-              (setq positions
-                    (cons same-indent
-                          (sort (delete same-indent positions) '<))))
-
-          ;; common special cases where we want to indent in from previous line
-          (if (or (js2-indent-case-block-p)
-                  (js2-indent-objlit-arg-p parse-status))
-              (setq positions
-                    (cons basic-offset
-                          (delete basic-offset positions))))
-
-          ;; record whether we're already sitting on one of the alternatives
-          (setq pos (member cur-indent positions))
-          (cond
-           ;; case 0:  we're one one of the alternatives and this is the
-           ;; first time they've pressed TAB on this line (best-guess).
-           ((and js2-mode-indent-ignore-first-tab
-                 pos
-                 ;; first time pressing TAB on this line?
-                 (not (eq js2-mode-last-indented-line current-line)))
-            ;; do nothing
-            (setq computed-pos nil))
-           ;; case 1:  only one computed position => use it
-           ((null (cdr positions))
-            (setq computed-pos 0))
-           ;; case 2:  not on any of the computed spots => use main spot
-           ((not pos)
-            (setq computed-pos 0))
-           ;; case 3:  on last position:  cycle to first position
-           ((null (cdr pos))
-            (setq computed-pos 0))
-           ;; case 4:  on intermediate position:  cycle to next position
-           (t
-            (setq computed-pos (js2-position (second pos) positions))))
-
-          ;; see if any hooks want to indent; otherwise we do it
-          (loop with result = nil
-                for hook in js2-indent-hook
-                while (null result)
-                do
-                (setq result (funcall hook positions computed-pos))
-                finally do
-                (unless (or result (null computed-pos))
-                  (indent-line-to (nth computed-pos positions)))))
-
-      ;; finally
-      (if js2-mode-indent-inhibit-undo
-          (setq buffer-undo-list old-buffer-undo-list))
-      ;; see commentary for `js2-mode-last-indented-line'
-      (setq js2-mode-last-indented-line current-line))))
-
-(defsubst js2-1-line-comment-continuation-p ()
-  "Return t if we're in a 1-line comment continuation.
-If so, we don't ever want to use bounce-indent."
-  (save-excursion
-    (save-match-data
-      (and (progn
-             (forward-line 0)
-             (looking-at "\\s-*//"))
-           (progn
-             (forward-line -1)
-             (forward-line 0)
-             (when (looking-at "\\s-*$")
-               (js2-backward-sws)
-               (forward-line 0))
-             (looking-at "\\s-*//"))))))
-
-(defun js2-indent-line ()
-  "Indent the current line as JavaScript source text."
-  (interactive)
-  (let (parse-status
-        current-indent
-        offset
-        indent-col
-        moved
-        ;; don't whine about errors/warnings when we're indenting.
-        ;; This has to be set before calling parse-partial-sexp below.
-        (inhibit-point-motion-hooks t))
-    (setq parse-status (save-excursion
-                          (parse-partial-sexp (point-min)
-                                              (point-at-bol)))
-          offset (- (point) (save-excursion
-                               (back-to-indentation)
-                               (setq current-indent (current-column))
-                               (point))))
-    (js2-with-underscore-as-word-syntax
-     (if (nth 4 parse-status)
-         (js2-lineup-comment parse-status)
-       (setq indent-col (js-proper-indentation parse-status))
-       ;; see comments below about js2-mode-last-indented-line
-       (when
-           (cond
-            ;; bounce-indenting is disabled during electric-key indent.
-            ;; It doesn't work well on first line of buffer.
-            ((and js2-bounce-indent-flag
-                  (not (js2-same-line (point-min)))
-                  (not (js2-1-line-comment-continuation-p)))
-             (js2-bounce-indent indent-col parse-status)
-             (setq moved t))
-            ;; just indent to the guesser's likely spot
-            ((/= current-indent indent-col)
-             (indent-line-to indent-col)
-             (setq moved t)))
-         (when (and moved (plusp offset))
-           (forward-char offset)))))))
-
-(defun js2-indent-region (start end)
-  "Indent the region, but don't use bounce indenting."
-  (let ((js2-bounce-indent-flag nil)
-        (indent-region-function nil))
-    (indent-region start end nil)))  ; nil for byte-compiler
-
-(provide 'js2-indent)
-
-;;; js2-indent.el ends here
-
-(eval-when-compile
-  (require 'cl))
-
-(require 'imenu)
-(require 'cc-cmds)  ; for `c-fill-paragraph'
-
-
-;;;###autoload (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
-
-;;;###autoload
-(defun js2-mode ()
-  "Major mode for editing JavaScript code."
-  (interactive)
-  (js2-mode-check-compat)
-  (kill-all-local-variables)
-  (set-syntax-table js2-mode-syntax-table)
-  (use-local-map js2-mode-map)
-  (setq major-mode 'js2-mode
-        mode-name "JavaScript-IDE"
-        comment-start "//"  ; used by comment-region; don't change it
-        comment-end "")
-  (setq local-abbrev-table js2-mode-abbrev-table)
-  (set (make-local-variable 'max-lisp-eval-depth)
-       (max max-lisp-eval-depth 3000))
-  (set (make-local-variable 'indent-line-function) #'js2-indent-line)
-  (set (make-local-variable 'indent-region-function) #'js2-indent-region)
-  (set (make-local-variable 'fill-paragraph-function) #'js2-fill-paragraph)
-  (set (make-local-variable 'before-save-hook) #'js2-before-save)
-  (set (make-local-variable 'next-error-function) #'js2-next-error)
-  (set (make-local-variable 'beginning-of-defun-function) #'js2-beginning-of-defun)
-  (set (make-local-variable 'end-of-defun-function) #'js2-end-of-defun)
-  ;; We un-confuse `parse-partial-sexp' by setting syntax-table properties
-  ;; for characters inside regexp literals.
-  (set (make-local-variable 'parse-sexp-lookup-properties) t)
-  ;; this is necessary to make `show-paren-function' work properly
-  (set (make-local-variable 'parse-sexp-ignore-comments) t)
-  ;; needed for M-x rgrep, among other things
-  (put 'js2-mode 'find-tag-default-function #'js2-mode-find-tag)
-
-  ;; some variables needed by cc-engine for paragraph-fill, etc.
-  (setq c-buffer-is-cc-mode t
-        c-comment-prefix-regexp js2-comment-prefix-regexp
-        c-paragraph-start js2-paragraph-start
-        c-paragraph-separate "$"
-        comment-start-skip js2-comment-start-skip
-        c-syntactic-ws-start js2-syntactic-ws-start
-        c-syntactic-ws-end js2-syntactic-ws-end
-        c-syntactic-eol js2-syntactic-eol)
-  (if js2-emacs22
-      (c-setup-paragraph-variables))
-
-  ;; We do our own syntax highlighting based on the parse tree.
-  ;; However, we want minor modes that add keywords to highlight properly
-  ;; (examples:  doxymacs, column-marker).  We do this by not letting
-  ;; font-lock unfontify anything, and telling it to fontify after we
-  ;; re-parse and re-highlight the buffer.  (We currently don't do any
-  ;; work with regions other than the whole buffer.)
-  (dolist (var '(font-lock-unfontify-buffer-function
-                 font-lock-unfontify-region-function))
-    (set (make-local-variable var) (lambda (&rest args) t)))
-
-  ;; Don't let font-lock do syntactic (string/comment) fontification.
-  (set (make-local-variable #'font-lock-syntactic-face-function)
-       (lambda (state) nil))
-
-  ;; Experiment:  make reparse-delay longer for longer files.
-  (if (plusp js2-dynamic-idle-timer-adjust)
-      (setq js2-idle-timer-delay
-            (* js2-idle-timer-delay
-               (/ (point-max) js2-dynamic-idle-timer-adjust))))
-
-  (add-hook 'change-major-mode-hook #'js2-mode-exit nil t)
-  (add-hook 'after-change-functions #'js2-mode-edit nil t)
-  (setq imenu-create-index-function #'js2-mode-create-imenu-index)
-  (imenu-add-to-menubar (concat "IM-" mode-name))
-  (when js2-mirror-mode
-    (js2-enter-mirror-mode))
-  (add-to-invisibility-spec '(js2-outline . t))
-  (set (make-local-variable 'line-move-ignore-invisible) t)
-  (set (make-local-variable 'forward-sexp-function) #'js2-mode-forward-sexp)
-  (setq js2-mode-functions-hidden nil
-        js2-mode-comments-hidden nil
-        js2-mode-buffer-dirty-p t
-        js2-mode-parsing nil)
-  (js2-reparse)
-  (run-hooks 'js2-mode-hook))
-
-(defun js2-mode-check-compat ()
-  "Signal an error if we can't run with this version of Emacs."
-  (if (and js2-mode-must-byte-compile
-           (not (byte-code-function-p (symbol-function 'js2-mode))))
-      (error "You must byte-compile js2-mode before using it."))
-  (if (and (boundp 'running-xemacs)
-           running-xemacs)
-      (error "js2-mode is not compatible with XEmacs"))
-  (unless (>= emacs-major-version 21)
-    (error "js2-mode requires GNU Emacs version 21 or higher")))
-
-(defun js2-mode-exit ()
-  (interactive)
-  (when js2-mode-node-overlay
-    (delete-overlay js2-mode-node-overlay)
-    (setq js2-mode-node-overlay nil))
-  (js2-remove-overlays)
-  (setq js2-mode-ast nil)
-  (remove-hook 'change-major-mode-hook #'js2-mode-exit t)
-  (remove-from-invisibility-spec '(js2-outline . t))
-  (js2-mode-show-all)
-  (js2-with-unmodifying-text-property-changes
-    (js2-clear-face (point-min) (point-max))))
-
-(defun js2-before-save ()
-  "Clean up whitespace before saving file.
-You can disable this by customizing `js2-cleanup-whitespace'."
-  (when js2-cleanup-whitespace
-    (let ((col (current-column)))
-      (delete-trailing-whitespace)
-      ;; don't change trailing whitespace on current line
-      (unless (eq (current-column) col)
-        (indent-to col)))))
-
-(defsubst js2-mode-reset-timer ()
-  (if js2-mode-parse-timer
-      (cancel-timer js2-mode-parse-timer))
-  (setq js2-mode-parsing nil)
-  (setq js2-mode-parse-timer
-        (run-with-idle-timer js2-idle-timer-delay nil #'js2-reparse)))
-
-(defun js2-mode-edit (beg end len)
-  "Schedule a new parse after buffer is edited."
-  (setq js2-mode-buffer-dirty-p t)
-  (js2-mode-hide-overlay)
-  (js2-mode-reset-timer))
-
-(defun js2-mode-run-font-lock ()
-  "Run `font-lock-fontify-buffer' after parsing/highlighting.
-This is intended to allow modes that install their own font-lock keywords
-to work with js2-mode.  In practice it never seems to work for long.
-Hopefully the Emacs maintainers can help figure out a way to make it work."
-  (when (and (boundp 'font-lock-keywords)
-             font-lock-keywords
-             (boundp 'font-lock-mode)
-             font-lock-mode)
-    ;; TODO:  font-lock and jit-lock really really REALLY don't want to
-    ;; play nicely with js2-mode.  They go out of their way to fail to
-    ;; provide any option for saying "look, fontify the goddamn buffer
-    ;; with just the keywords already".  Argh.
-    (setq font-lock-defaults (list font-lock-keywords 'keywords-only))
-    (let (font-lock-verbose)
-      (font-lock-default-fontify-buffer))))
-
-(defun js2-reparse (&optional force)
-  "Re-parse current buffer after user finishes some data entry.
-If we get any user input while parsing, including cursor motion,
-we discard the parse and reschedule it.  If FORCE is nil, then the
-buffer will only rebuild its `js2-mode-ast' if the buffer is dirty."
-  (let (time
-        interrupted-p
-        (js2-compiler-strict-mode js2-mode-show-strict-warnings))
-    (unless js2-mode-parsing
-      (setq js2-mode-parsing t)
-      (unwind-protect
-          (when (or js2-mode-buffer-dirty-p force)
-            (js2-remove-overlays)
-            (js2-with-unmodifying-text-property-changes
-              (setq js2-mode-buffer-dirty-p nil
-                    js2-mode-fontifications nil
-                    js2-mode-deferred-properties nil)
-              (if js2-mode-verbose-parse-p
-                  (message "parsing..."))
-              (setq time
-                    (js2-time
-                     (setq interrupted-p
-                           (catch 'interrupted
-                             (setq js2-mode-ast (js2-parse))
-                             (js2-mode-fontify-regions)
-                             (js2-mode-remove-suppressed-warnings)
-                             (js2-mode-show-warnings)
-                             (js2-mode-show-errors)
-                             (js2-mode-run-font-lock)  ; note:  doesn't work
-                             (if (>= js2-highlight-level 1)
-                                 (js2-highlight-jsdoc js2-mode-ast))
-                             nil))))
-              (if interrupted-p
-                  (progn
-                    ;; unfinished parse => try again
-                    (setq js2-mode-buffer-dirty-p t)
-                    (js2-mode-reset-timer))
-                (if js2-mode-verbose-parse-p
-                    (message "Parse time: %s" time)))))
-        ;; finally
-        (setq js2-mode-parsing nil)
-        (unless interrupted-p
-          (setq js2-mode-parse-timer nil))))))
-
-(defun js2-mode-show-node ()
-  "Debugging aid:  highlight selected AST node on mouse click."
-  (interactive)
-  (let ((node (js2-node-at-point))
-        beg
-        end)
-    (when js2-mode-show-overlay
-      (if (null node)
-          (message "No node found at location %s" (point))
-        (setq beg (js2-node-abs-pos node)
-              end (+ beg (js2-node-len node)))
-        (if js2-mode-node-overlay
-            (move-overlay js2-mode-node-overlay beg end)
-          (setq js2-mode-node-overlay (make-overlay beg end))
-          (overlay-put js2-mode-node-overlay 'face 'highlight))
-        (js2-with-unmodifying-text-property-changes
-          (put-text-property beg end 'point-left #'js2-mode-hide-overlay))
-        (message "%s, parent: %s"
-                 (js2-node-short-name node)
-                 (if (js2-node-parent node)
-                     (js2-node-short-name (js2-node-parent node))
-                   "nil"))))))
-
-(defun js2-mode-hide-overlay (&optional p1 p2)
-  "Remove the debugging overlay when the point moves."
-  (when js2-mode-node-overlay
-    (let ((beg (overlay-start js2-mode-node-overlay))
-          (end (overlay-end js2-mode-node-overlay)))
-      ;; Sometimes we're called spuriously.
-      (unless (and p2
-                   (>= p2 beg)
-                   (<= p2 end))
-        (js2-with-unmodifying-text-property-changes
-          (remove-text-properties beg end '(point-left nil)))
-        (delete-overlay js2-mode-node-overlay)
-        (setq js2-mode-node-overlay nil)))))
-
-(defun js2-mode-reset ()
-  "Debugging helper; resets everything."
-  (interactive)
-  (js2-mode-exit)
-  (js2-mode))
-
-(defsubst js2-mode-show-warn-or-err (e face)
-  "Highlight a warning or error E with FACE.
-E is a list of ((MSG-KEY MSG-ARG) BEG END)."
-  (let* ((key (first e))
-         (beg (second e))
-         (end (+ beg (third e)))
-         ;; Don't inadvertently go out of bounds.
-         (beg (max (point-min) (min beg (point-max))))
-         (end (max (point-min) (min end (point-max))))
-         (js2-highlight-level 3)    ; so js2-set-face is sure to fire
-         (ovl (make-overlay beg end)))
-    (overlay-put ovl 'face face)
-    (overlay-put ovl 'js2 t)
-    (put-text-property beg end 'help-echo (js2-get-msg key))
-    (put-text-property beg end 'point-entered #'js2-echo-error)))
-
-(defun js2-remove-overlays ()
-  "Remove overlays from buffer that have a `js2' property."
-  (let ((beg (point-min))
-        (end (point-max)))
-    (save-excursion
-      (dolist (o (overlays-in beg end))
-        (when (overlay-get o 'js2)
-          (delete-overlay o))))))
-
-(defun js2-mode-fontify-regions ()
-  "Apply fontifications recorded during parsing."
-  ;; We defer clearing faces as long as possible to eliminate flashing.
-  (js2-clear-face (point-min) (point-max))
-  ;; have to reverse the recorded fontifications so that errors and
-  ;; warnings overwrite the normal fontifications
-  (dolist (f (nreverse js2-mode-fontifications))
-    (put-text-property (first f) (second f) 'face (third f)))
-  (setq js2-mode-fontifications nil)
-  (dolist (p js2-mode-deferred-properties)
-    (apply #'put-text-property p))
-  (setq js2-mode-deferred-properties nil))
-
-(defun js2-mode-show-errors ()
-  "Highlight syntax errors."
-  (when js2-mode-show-parse-errors
-    (dolist (e (js2-ast-root-errors js2-mode-ast))
-      (js2-mode-show-warn-or-err e 'js2-error-face))))
-
-(defun js2-mode-remove-suppressed-warnings ()
-  "Take suppressed warnings out of the AST warnings list.
-This ensures that the counts and `next-error' are correct."
-  (setf (js2-ast-root-warnings js2-mode-ast)
-        (js2-delete-if
-         (lambda (e)
-           (let ((key (caar e)))
-             (or
-              (and (not js2-strict-trailing-comma-warning)
-                   (string-match "trailing\\.comma" key))
-              (and (not js2-strict-cond-assign-warning)
-                   (string= key "msg.equal.as.assign"))
-              (and js2-missing-semi-one-line-override
-                   (string= key "msg.missing.semi")
-                   (let* ((beg (second e))
-                          (node (js2-node-at-point beg))
-                          (fn (js2-mode-find-parent-fn node))
-                          (body (and fn (js2-function-node-body fn)))
-                          (lc (and body (js2-node-abs-pos body)))
-                          (rc (and lc (+ lc (js2-node-len body)))))
-                     (and fn
-                          (or (null body)
-                              (save-excursion
-                                (goto-char beg)
-                                (and (js2-same-line lc)
-                                     (js2-same-line rc))))))))))
-         (js2-ast-root-warnings js2-mode-ast))))
-
-(defun js2-mode-show-warnings ()
-  "Highlight strict-mode warnings."
-  (when js2-mode-show-strict-warnings
-    (dolist (e (js2-ast-root-warnings js2-mode-ast))
-      (js2-mode-show-warn-or-err e 'js2-warning-face))))
-
-(defun js2-echo-error (old-point new-point)
-  "Called by point-motion hooks."
-  (let ((msg (get-text-property new-point 'help-echo)))
-    (if msg
-        (message msg))))
-
-(defalias #'js2-echo-help #'js2-echo-error)
-
-(defun js2-enter-key ()
-  "Handle user pressing the Enter key."
-  (interactive)
-  (let ((parse-status (save-excursion
-                        (parse-partial-sexp (point-min) (point)))))
-    (cond
-     ;; check if we're inside a string
-     ((nth 3 parse-status)
-      (js2-mode-split-string parse-status))
-     ;; check if inside a block comment
-     ((nth 4 parse-status)
-      (js2-mode-extend-comment))
-     (t
-      ;; should probably figure out what the mode-map says we should do
-      (if js2-indent-on-enter-key
-          (let ((js2-bounce-indent-flag nil))
-            (js2-indent-line)))
-      (insert "\n")
-      (if js2-enter-indents-newline
-          (let ((js2-bounce-indent-flag nil))
-            (js2-indent-line)))))))
-
-(defun js2-mode-split-string (parse-status)
-  "Turn a newline in mid-string into a string concatenation."
-  (let* ((col (current-column))
-         (quote-char (nth 3 parse-status))
-         (quote-string (string quote-char))
-         (string-beg (nth 8 parse-status))
-         (indent (save-match-data
-                   (or
-                    (save-excursion
-                      (back-to-indentation)
-                      (if (looking-at "\\+")
-                          (current-column)))
-                    (save-excursion
-                      (goto-char string-beg)
-                      (if (looking-back "\\+\\s-+")
-                          (goto-char (match-beginning 0)))
-                      (current-column))))))
-    (insert quote-char "\n")
-    (indent-to indent)
-    (insert "+ " quote-string)
-    (when (eolp)
-      (insert quote-string)
-      (backward-char 1))))
-
-(defun js2-mode-extend-comment ()
-  "When inside a comment block, add comment prefix."
-  (let (star single col first-line needs-close)
-    (save-excursion
-      (back-to-indentation)
-      (cond
-       ((looking-at "\\*[^/]")
-        (setq star t
-              col (current-column)))
-       ((looking-at "/\\*")
-        (setq star t
-              first-line t
-              col (1+ (current-column))))
-       ((looking-at "//")
-        (setq single t
-              col (current-column)))))
-    ;; Heuristic for whether we need to close the comment:
-    ;; if we've got a parse error here, assume it's an unterminated
-    ;; comment.
-    (setq needs-close
-          (or
-           (eq (get-text-property (1- (point)) 'point-entered)
-               'js2-echo-error)
-           ;; The heuristic above doesn't work well when we're
-           ;; creating a comment and there's another one downstream,
-           ;; as our parser thinks this one ends at the end of the
-           ;; next one.  (You can have a /* inside a js block comment.)
-           ;; So just close it if the next non-ws char isn't a *.
-           (and first-line
-                (eolp)
-                (save-excursion
-                  (skip-syntax-forward " ")
-                  (not (eq (char-after) ?*))))))
-    (insert "\n")
-    (cond
-     (star
-      (indent-to col)
-      (insert "* ")
-      (if (and first-line needs-close)
-          (save-excursion
-            (insert "\n")
-            (indent-to col)
-            (insert "*/"))))
-     (single
-      (when (save-excursion
-              (and (zerop (forward-line 1))
-                   (looking-at "\\s-*//")))
-        (indent-to col)
-        (insert "// "))))))
-
-(defun js2-fill-string (beg quote)
-  "Line-wrap a single-line string into a multi-line string.
-BEG is the string beginning, QUOTE is the quote char."
-  (let* ((squote (string quote))
-         (end (if (re-search-forward (concat "[^\\]" squote)
-                                     (point-at-eol) t)
-                  (1+ (match-beginning 0))
-                (point-at-eol)))
-         (tag (make-marker))
-         (fill-column (- fill-column 4)))  ; make room
-    (unwind-protect
-        (progn
-          (move-marker tag end)
-          (fill-paragraph nil)
-          (goto-char beg)
-          (while (not (js2-same-line tag))
-            (goto-char (point-at-eol))
-            (insert squote)
-            (when (zerop (forward-line 1))
-              (back-to-indentation)
-              (if (looking-at (concat squote "\\s-*$"))
-                  (progn
-                    (setq end (point-at-eol))
-                    (forward-line -1)
-                    (delete-region (point-at-eol) end))
-                (insert "+ " squote)))))
-      (move-marker tag nil))))
-
-(defun js2-fill-paragraph (arg)
-  "Fill paragraph after point.  Prefix ARG means justify as well.
-Has special handling for filling in comments and strings."
-  (let* ((parse-status (save-excursion
-                         (parse-partial-sexp (point-min) (point))))
-         (quote-char (or (nth 3 parse-status)
-                         (save-match-data
-                           (if (looking-at "[\"\']")
-                               (char-after))))))
-    (cond
-     (quote-char
-      (js2-fill-string (or (nth 8 parse-status)
-                           (point))
-                       quote-char)
-      t) ; or fill-paragraph does evil things afterwards
-     ((nth 4 parse-status)  ; in block comment?
-      (js2-fill-comment parse-status arg))
-     (t
-      (fill-paragraph arg)))))
-
-(defun js2-fill-comment (parse-status arg)
-  "Fill-paragraph in a block comment."
-  (let* ((beg (nth 8 parse-status))
-         (end (save-excursion
-                (goto-char beg)
-                (re-search-forward "[^\\]\\*/" nil t)))
-         indent
-         end-marker)
-    (when end
-      (setq end-marker (make-marker))
-      (move-marker end-marker end))
-    (when (and end js2-mode-squeeze-spaces)
-      (save-excursion
-        (save-restriction
-          (narrow-to-region beg end)
-          (goto-char (point-min))
-          (while (re-search-forward "[ \t][ \t]+" nil t)
-            (replace-match " ")))))
-    ;; `c-fill-paragraph' doesn't indent the continuation stars properly
-    ;; if the comment isn't left-justified.  They align to the first star
-    ;; on the first continuation line after the comment-open, so we make
-    ;; sure the first continuation line has the proper indentation.
-    (save-excursion
-      (goto-char beg)
-      (setq indent (1+ (current-column)))
-      (goto-char (point-at-eol))
-      (skip-chars-forward " \t\r\n")
-      (indent-line-to indent)
-
-      ;; Invoke `c-fill-paragraph' from the first continuation line,
-      ;; since it provides better results.  Otherwise if you're on the
-      ;; last line, it doesn't prefix with stars the way you'd expect.
-      ;; TODO:  write our own fill function that works in Emacs 21
-      (c-fill-paragraph arg))
-
-    ;; last line is typically indented wrong, so fix it
-    (when end-marker
-      (save-excursion
-        (goto-char end-marker)
-        (js2-indent-line)))))
-
-(defun js2-beginning-of-line ()
-  "Toggles point between bol and first non-whitespace char in line.
-Also moves past comment delimiters when inside comments."
-  (interactive)
-  (let (node beg)
-    (cond
-     ((bolp)
-      (back-to-indentation))
-     ((looking-at "//")
-      (skip-chars-forward "/ \t"))
-     ((and (eq (char-after) ?*)
-           (setq node (js2-comment-at-point))
-           (memq (js2-comment-node-format node) '(jsdoc block))
-           (save-excursion
-             (skip-chars-backward " \t")
-             (bolp)))
-      (skip-chars-forward "\* \t"))
-     (t
-      (goto-char (point-at-bol))))))
-
-(defun js2-end-of-line ()
-  "Toggles point between eol and last non-whitespace char in line."
-  (interactive)
-  (if (eolp)
-      (skip-chars-backward " \t")
-    (goto-char (point-at-eol))))
-
-(defun js2-enter-mirror-mode()
-  "Turns on mirror mode, where quotes, brackets etc are mirrored automatically
-  on insertion."
-  (interactive)
-  (define-key js2-mode-map (read-kbd-macro "{")  'js2-mode-match-curly)
-  (define-key js2-mode-map (read-kbd-macro "}")  'js2-mode-magic-close-paren)
-  (define-key js2-mode-map (read-kbd-macro "\"") 'js2-mode-match-double-quote)
-  (define-key js2-mode-map (read-kbd-macro "'")  'js2-mode-match-single-quote)
-  (define-key js2-mode-map (read-kbd-macro "(")  'js2-mode-match-paren)
-  (define-key js2-mode-map (read-kbd-macro ")")  'js2-mode-magic-close-paren)
-  (define-key js2-mode-map (read-kbd-macro "[")  'js2-mode-match-bracket)
-  (define-key js2-mode-map (read-kbd-macro "]")  'js2-mode-magic-close-paren))
-
-(defun js2-leave-mirror-mode()
-  "Turns off mirror mode."
-  (interactive)
-  (dolist (key '("{" "\"" "'" "(" ")" "[" "]"))
-    (define-key js2-mode-map (read-kbd-macro key) 'self-insert-command)))
-
-(defsubst js2-mode-inside-string ()
-  "Return non-nil if inside a string.
-Actually returns the quote character that begins the string."
-   (let ((parse-state (save-excursion
-                        (parse-partial-sexp (point-min) (point)))))
-      (nth 3 parse-state)))
-
-(defsubst js2-mode-inside-comment-or-string ()
-  "Return non-nil if inside a comment or string."
-  (or
-   (let ((comment-start
-          (save-excursion
-            (goto-char (point-at-bol))
-            (if (re-search-forward "//" (point-at-eol) t)
-                (match-beginning 0)))))
-     (and comment-start
-          (<= comment-start (point))))
-   (let ((parse-state (save-excursion
-                        (parse-partial-sexp (point-min) (point)))))
-     (or (nth 3 parse-state)
-         (nth 4 parse-state)))))
-
-(defun js2-mode-match-curly (arg)
-  "Insert matching curly-brace."
-  (interactive "p")
-  (insert "{")
-  (if current-prefix-arg
-      (save-excursion
-        (insert "}"))
-    (unless (or (not (looking-at "\\s-*$"))
-                (js2-mode-inside-comment-or-string))
-      (undo-boundary)
-
-      ;; absolutely mystifying bug:  when inserting the next "\n",
-      ;; the buffer-undo-list is given two new entries:  the inserted range,
-      ;; and the incorrect position of the point.  It's recorded incorrectly
-      ;; as being before the opening "{", not after it.  But it's recorded
-      ;; as the correct value if you're debugging `js2-mode-match-curly'
-      ;; in edebug.  I have no idea why it's doing this, but incrementing
-      ;; the inserted position fixes the problem, so that the undo takes us
-      ;; back to just after the user-inserted "{".
-      (insert "\n")
-      (ignore-errors
-        (incf (cadr buffer-undo-list)))
-
-      (js2-indent-line)
-      (save-excursion
-        (insert "\n}")
-        (let ((js2-bounce-indent-flag (js2-code-at-bol-p)))
-          (js2-indent-line))))))
-
-(defun js2-mode-match-bracket ()
-  "Insert matching bracket."
-  (interactive)
-  (insert "[")
-  (unless (or (not (looking-at "\\s-*$"))
-              (js2-mode-inside-comment-or-string))
-    (save-excursion
-      (insert "]"))
-    (when js2-auto-indent-flag
-      (let ((js2-bounce-indent-flag (js2-code-at-bol-p)))
-        (js2-indent-line)))))
-
-(defun js2-mode-match-paren ()
-  "Insert matching paren unless already inserted."
-  (interactive)
-  (insert "(")
-  (unless (or (not (looking-at "\\s-*$"))
-              (js2-mode-inside-comment-or-string))
-    (save-excursion
-      (insert ")"))
-    (when js2-auto-indent-flag
-      (let ((js2-bounce-indent-flag (js2-code-at-bol-p)))
-        (js2-indent-line)))))
-
-(defsubst js2-match-quote (quote-string)
-  (let ((start-quote (js2-mode-inside-string)))
-    (cond
-     ;; inside a comment - don't do quote-matching, since we can't
-     ;; reliably figure out if we're in a string inside the comment
-     ((js2-comment-at-point)
-      (insert quote-string))
-     ((not start-quote)
-      ;; not in string => insert matched quotes
-      (insert quote-string)
-      ;; exception:  if we're just before a word, don't double it.
-      (unless (looking-at "[^ \t\r\n]")
-        (save-excursion
-          (insert quote-string))))
-     ((looking-at quote-string)
-      (if (looking-back "[^\\]\\\\")
-          (insert quote-string)
-        (forward-char 1)))
-     ((and js2-mode-escape-quotes
-           (save-excursion
-             (save-match-data
-               (re-search-forward quote-string (point-at-eol) t))))
-      ;; inside terminated string, escape quote (unless already escaped)
-      (insert (if (looking-back "[^\\]\\\\")
-                  quote-string
-                (concat "\\" quote-string))))
-     (t
-      (insert quote-string)))))        ; else terminate the string
-
-(defun js2-mode-match-single-quote ()
-  "Insert matching single-quote."
-  (interactive)
-  (let ((parse-status (parse-partial-sexp (point-min) (point))))
-    ;; don't match inside comments, since apostrophe is more common
-    (if (nth 4 parse-status)
-        (insert "'")
-      (js2-match-quote "'"))))
-
-(defun js2-mode-match-double-quote ()
-  "Insert matching double-quote."
-  (interactive)
-  (js2-match-quote "\""))
-
-(defun js2-mode-magic-close-paren ()
-  "Skip over close-paren rather than inserting, where appropriate.
-Uses some heuristics to try to figure out the right thing to do."
-  (interactive)
-  (let* ((parse-status (parse-partial-sexp (point-min) (point)))
-         (open-pos (nth 1 parse-status))
-         (close last-input-char)
-         (open (cond
-                ((eq close 41)  ; close-paren
-                 40)            ; open-paren
-                ((eq close 93)  ; close-bracket
-                 91)            ; open-bracket
-                ((eq close ?})
-                 ?{)
-                (t nil))))
-    (if (and (looking-at (string close))
-             (eq open (char-after open-pos))
-             (js2-same-line open-pos))
-        (forward-char 1)
-      (insert (string close)))
-    (blink-matching-open)))
-
-(defun js2-mode-wait-for-parse (callback)
-  "Invoke CALLBACK when parsing is finished.
-If parsing is already finished, calls CALLBACK immediately."
-  (if (not js2-mode-buffer-dirty-p)
-      (funcall callback)
-    (push callback js2-mode-pending-parse-callbacks)
-    (add-hook 'js2-parse-finished-hook #'js2-mode-parse-finished)))
-
-(defun js2-mode-parse-finished ()
-  "Invoke callbacks in `js2-mode-pending-parse-callbacks'."
-  ;; We can't let errors propagate up, since it prevents the
-  ;; `js2-parse' method from completing normally and returning
-  ;; the ast, which makes things mysteriously not work right.
-  (unwind-protect
-      (dolist (cb js2-mode-pending-parse-callbacks)
-        (condition-case err
-            (funcall cb)
-          (error (message "%s" err))))
-    (setq js2-mode-pending-parse-callbacks nil)))
-
-(defun js2-mode-flag-region (from to flag)
-  "Hide or show text from FROM to TO, according to FLAG.
-If FLAG is nil then text is shown, while if FLAG is t the text is hidden.
-Returns the created overlay if FLAG is non-nil."
-  (remove-overlays from to 'invisible 'js2-outline)
-  (when flag
-    (let ((o (make-overlay from to)))
-      (overlay-put o 'invisible 'js2-outline)
-      (overlay-put o 'isearch-open-invisible
-                   'js2-isearch-open-invisible)
-      o)))
-
-;; Function to be set as an outline-isearch-open-invisible' property
-;; to the overlay that makes the outline invisible (see
-;; `js2-mode-flag-region').
-(defun js2-isearch-open-invisible (overlay)
-  ;; We rely on the fact that isearch places point on the matched text.
-  (js2-mode-show-element))
-
-(defun js2-mode-invisible-overlay-bounds (&optional pos)
-  "Return cons cell of bounds of folding overlay at POS.
-Returns nil if not found."
-  (let ((overlays (overlays-at (or pos (point))))
-        o)
-    (while (and overlays
-                (not o))
-      (if (overlay-get (car overlays) 'invisible)
-          (setq o (car overlays))
-        (setq overlays (cdr overlays))))
-    (if o
-        (cons (overlay-start o) (overlay-end o)))))
-
-(defun js2-mode-function-at-point (&optional pos)
-  "Return the innermost function node enclosing current point.
-Returns nil if point is not in a function."
-  (let ((node (js2-node-at-point pos)))
-    (while (and node (not (js2-function-node-p node)))
-      (setq node (js2-node-parent node)))
-    (if (js2-function-node-p node)
-        node)))
-
-(defun js2-mode-toggle-element ()
-  "Hide or show the foldable element at the point."
-  (interactive)
-  (let (comment fn pos)
-    (save-excursion
-      (save-match-data
-        (cond
-         ;; /* ... */ comment?
-         ((js2-block-comment-p (setq comment (js2-comment-at-point)))
-          (if (js2-mode-invisible-overlay-bounds
-               (setq pos (+ 3 (js2-node-abs-pos comment))))
-              (progn
-                (goto-char pos)
-                (js2-mode-show-element))
-            (js2-mode-hide-element)))
-
-         ;; //-comment?
-         ((save-excursion
-            (back-to-indentation)
-            (looking-at js2-mode-//-comment-re))
-          (js2-mode-toggle-//-comment))
-
-         ;; function?
-         ((setq fn (js2-mode-function-at-point))
-          (setq pos (and (js2-function-node-body fn)
-                         (js2-node-abs-pos (js2-function-node-body fn))))
-          (goto-char (1+ pos))
-          (if (js2-mode-invisible-overlay-bounds)
-              (js2-mode-show-element)
-            (js2-mode-hide-element)))
-         (t
-          (message "Nothing at point to hide or show")))))))
-
-(defun js2-mode-hide-element ()
-  "Fold/hide contents of a block, showing ellipses.
-Show the hidden text with \\[js2-mode-show-element]."
-  (interactive)
-  (if js2-mode-buffer-dirty-p
-      (js2-mode-wait-for-parse #'js2-mode-hide-element))
-  (let (node body beg end)
-    (cond
-     ((js2-mode-invisible-overlay-bounds)
-      (message "already hidden"))
-     (t
-      (setq node (js2-node-at-point))
-      (cond
-       ((js2-block-comment-p node)
-        (js2-mode-hide-comment node))
-       (t
-        (while (and node (not (js2-function-node-p node)))
-          (setq node (js2-node-parent node)))
-        (if (and node
-                 (setq body (js2-function-node-body node)))
-            (progn
-              (setq beg (js2-node-abs-pos body)
-                    end (+ beg (js2-node-len body)))
-              (js2-mode-flag-region (1+ beg) (1- end) 'hide))
-          (message "No collapsable element found at point"))))))))
-
-(defun js2-mode-show-element ()
-  "Show the hidden element at current point."
-  (interactive)
-  (let ((bounds (js2-mode-invisible-overlay-bounds)))
-    (if bounds
-        (js2-mode-flag-region (car bounds) (cdr bounds) nil)
-      (message "Nothing to un-hide"))))
-
-(defun js2-mode-show-all ()
-  "Show all of the text in the buffer."
-  (interactive)
-  (js2-mode-flag-region (point-min) (point-max) nil))
-
-(defun js2-mode-toggle-hide-functions ()
-  (interactive)
-  (if js2-mode-functions-hidden
-      (js2-mode-show-functions)
-    (js2-mode-hide-functions)))
-
-(defun js2-mode-hide-functions ()
-  "Hides all non-nested function bodies in the buffer.
-Use \\[js2-mode-show-all] to reveal them, or \\[js2-mode-show-element]
-to open an individual entry."
-  (interactive)
-  (if js2-mode-buffer-dirty-p
-      (js2-mode-wait-for-parse #'js2-mode-hide-functions))
-  (if (null js2-mode-ast)
-      (message "Oops - parsing failed")
-    (setq js2-mode-functions-hidden t)
-    (js2-visit-ast js2-mode-ast #'js2-mode-function-hider)))
-
-(defun js2-mode-function-hider (n endp)
-  (when (not endp)
-    (let ((tt (js2-node-type n))
-          body beg end)
-      (cond
-       ((and (= tt js2-FUNCTION)
-             (setq body (js2-function-node-body n)))
-        (setq beg (js2-node-abs-pos body)
-              end (+ beg (js2-node-len body)))
-        (js2-mode-flag-region (1+ beg) (1- end) 'hide)
-        nil)   ; don't process children of function
-       (t
-        t))))) ; keep processing other AST nodes
-
-(defun js2-mode-show-functions ()
-  "Un-hide any folded function bodies in the buffer."
-  (interactive)
-  (setq js2-mode-functions-hidden nil)
-  (save-excursion
-    (goto-char (point-min))
-    (while (/= (goto-char (next-overlay-change (point)))
-               (point-max))
-      (dolist (o (overlays-at (point)))
-        (when (and (overlay-get o 'invisible)
-                   (not (overlay-get o 'comment)))
-          (js2-mode-flag-region (overlay-start o) (overlay-end o) nil))))))
-
-(defun js2-mode-hide-comment (n)
-  (let* ((head (if (eq (js2-comment-node-format n) 'jsdoc)
-                   3                    ; /**
-                 2))                    ; /*
-         (beg (+ (js2-node-abs-pos n) head))
-         (end (- (+ beg (js2-node-len n)) head 2))
-         (o (js2-mode-flag-region beg end 'hide)))
-    (overlay-put o 'comment t)))
-
-(defun js2-mode-toggle-hide-comments ()
-  "Folds all block comments in the buffer.
-Use \\[js2-mode-show-all] to reveal them, or \\[js2-mode-show-element]
-to open an individual entry."
-  (interactive)
-  (if js2-mode-comments-hidden
-      (js2-mode-show-comments)
-    (js2-mode-hide-comments)))
-
-(defun js2-mode-hide-comments ()
-  (interactive)
-  (if js2-mode-buffer-dirty-p
-      (js2-mode-wait-for-parse #'js2-mode-hide-comments))
-  (if (null js2-mode-ast)
-      (message "Oops - parsing failed")
-    (setq js2-mode-comments-hidden t)
-    (dolist (n (js2-ast-root-comments js2-mode-ast))
-      (let ((format (js2-comment-node-format n)))
-        (when (js2-block-comment-p n)
-          (js2-mode-hide-comment n))))
-    (js2-mode-hide-//-comments)))
-
-(defsubst js2-mode-extend-//-comment (direction)
-  "Find start or end of a block of similar //-comment lines.
-DIRECTION is -1 to look back, 1 to look forward.
-INDENT is the indentation level to match.
-Returns the end-of-line position of the furthest adjacent
-//-comment line with the same indentation as the current line.
-If there is no such matching line, returns current end of line."
-  (let ((pos (point-at-eol))
-        (indent (current-indentation)))
-    (save-excursion
-      (save-match-data
-        (while (and (zerop (forward-line direction))
-                    (looking-at js2-mode-//-comment-re)
-                    (eq indent (length (match-string 1))))
-          (setq pos (point-at-eol)))
-      pos))))
-
-(defun js2-mode-hide-//-comments ()
-  "Fold adjacent 1-line comments, showing only snippet of first one."
-  (let (beg end)
-    (save-excursion
-      (save-match-data
-        (goto-char (point-min))
-        (while (re-search-forward js2-mode-//-comment-re nil t)
-          (setq beg (point)
-                end (js2-mode-extend-//-comment 1))
-          (unless (eq beg end)
-            (overlay-put (js2-mode-flag-region beg end 'hide)
-                         'comment t))
-          (goto-char end)
-          (forward-char 1))))))
-
-(defun js2-mode-toggle-//-comment ()
-  "Fold or un-fold any multi-line //-comment at point.
-Caller should have determined that this line starts with a //-comment."
-  (let* ((beg (point-at-eol))
-         (end beg))
-    (save-excursion
-      (goto-char end)
-      (if (js2-mode-invisible-overlay-bounds)
-          (js2-mode-show-element)
-        ;; else hide the comment
-        (setq beg (js2-mode-extend-//-comment -1)
-              end (js2-mode-extend-//-comment 1))
-        (unless (eq beg end)
-          (overlay-put (js2-mode-flag-region beg end 'hide)
-                       'comment t))))))
-
-(defun js2-mode-show-comments ()
-  "Un-hide any hidden comments, leaving other hidden elements alone."
-  (interactive)
-  (setq js2-mode-comments-hidden nil)
-  (save-excursion
-    (goto-char (point-min))
-    (while (/= (goto-char (next-overlay-change (point)))
-               (point-max))
-      (dolist (o (overlays-at (point)))
-        (when (overlay-get o 'comment)
-          (js2-mode-flag-region (overlay-start o) (overlay-end o) nil))))))
-
-(defun js2-mode-display-warnings-and-errors ()
-  "Turn on display of warnings and errors."
-  (interactive)
-  (setq js2-mode-show-parse-errors t
-        js2-mode-show-strict-warnings t)
-  (js2-reparse 'force))
-
-(defun js2-mode-hide-warnings-and-errors ()
-  "Turn off display of warnings and errors."
-  (interactive)
-  (setq js2-mode-show-parse-errors nil
-        js2-mode-show-strict-warnings nil)
-  (js2-reparse 'force))
-
-(defun js2-mode-toggle-warnings-and-errors ()
-  "Toggle the display of warnings and errors.
-Some users don't like having warnings/errors reported while they type."
-  (interactive)
-  (setq js2-mode-show-parse-errors (not js2-mode-show-parse-errors)
-        js2-mode-show-strict-warnings (not js2-mode-show-strict-warnings))
-  (if (interactive-p)
-      (message "warnings and errors %s"
-               (if js2-mode-show-parse-errors
-                   "enabled"
-                 "disabled")))
-  (js2-reparse 'force))
-
-(defun js2-mode-customize ()
-  (interactive)
-  (customize-group 'js2-mode))
-
-(defun js2-mode-forward-sexp (&optional arg)
-  "Move forward across one statement or balanced expression.
-With ARG, do it that many times.  Negative arg -N means
-move backward across N balanced expressions."
-  (interactive "p")
-  (setq arg (or arg 1))
-  (if js2-mode-buffer-dirty-p
-      (js2-mode-wait-for-parse #'js2-mode-forward-sexp))
-  (let (node end (start (point)))
-    (cond
-     ;; backward-sexp
-     ;; could probably make this "better" for some cases:
-     ;;  - if in statement block (e.g. function body), go to parent
-     ;;  - infix exprs like (foo in bar) - maybe go to beginning
-     ;;    of infix expr if in the right-side expression?
-     ((and arg (minusp arg))
-      (dotimes (i (- arg))
-        (js2-backward-sws)
-        (forward-char -1)  ; enter the node we backed up to
-        (setq node (js2-node-at-point (point) t))
-        (goto-char (if node
-                       (js2-node-abs-pos node)
-                     (point-min)))))
-    (t
-     ;; forward-sexp
-     (js2-forward-sws)
-     (dotimes (i arg)
-       (js2-forward-sws)
-       (setq node (js2-node-at-point (point) t)
-             end (if node (+ (js2-node-abs-pos node)
-                             (js2-node-len node))))
-       (goto-char (or end (point-max))))))))
-
-(defun js2-next-error (&optional arg reset)
-  "Move to next parse error.
-Typically invoked via \\[next-error].
-ARG is the number of errors, forward or backward, to move.
-RESET means start over from the beginning."
-  (interactive "p")
-  (if (or (null js2-mode-ast)
-          (and (null (js2-ast-root-errors js2-mode-ast))
-               (null (js2-ast-root-warnings js2-mode-ast))))
-      (message "No errors")
-    (when reset
-      (goto-char (point-min)))
-    (let* ((errs (copy-sequence
-                  (append (js2-ast-root-errors js2-mode-ast)
-                          (js2-ast-root-warnings js2-mode-ast))))
-           (continue t)
-           (start (point))
-           (count (or arg 1))
-           (backward (minusp count))
-           (sorter (if backward '> '<))
-           (stopper (if backward '< '>))
-           (count (abs count))
-           all-errs
-           err)
-      ;; sort by start position
-      (setq errs (sort errs (lambda (e1 e2)
-                              (funcall sorter (second e1) (second e2))))
-            all-errs errs)
-      ;; find nth error with pos > start
-      (while (and errs continue)
-        (when (funcall stopper (cadar errs) start)
-          (setq err (car errs))
-          (if (zerop (decf count))
-              (setq continue nil)))
-        (setq errs (cdr errs)))
-      (if err
-          (goto-char (second err))
-        ;; wrap around to first error
-        (goto-char (second (car all-errs)))
-        ;; if we were already on it, echo msg again
-        (if (= (point) start)
-            (js2-echo-error (point) (point)))))))
-
-(defun js2-mouse-3 ()
-  "Make right-click move the point to the click location.
-This makes right-click context menu operations a bit more intuitive.
-The point will not move if the region is active, however, to avoid
-destroying the region selection."
-  (interactive)
-  (when (and js2-move-point-on-right-click
-             (not mark-active))
-    (let ((e last-input-event))
-      (ignore-errors
-        (goto-char (cadadr e))))))
-
-(defun js2-mode-create-imenu-index ()
-  "Return an alist for `imenu--index-alist'."
-  ;; This is built up in `js2-parse-record-imenu' during parsing.
-  (when js2-mode-ast
-    ;; if we have an ast but no recorder, they're requesting a rescan
-    (unless js2-imenu-recorder
-      (js2-reparse 'force))
-    (prog1
-        (js2-build-imenu-index)
-      (setq js2-imenu-recorder nil
-            js2-imenu-function-map nil))))
-
-(defun js2-mode-find-tag ()
-  "Replacement for `find-tag-default'.
-`find-tag-default' returns a ridiculous answer inside comments."
-  (let (beg end)
-    (js2-with-underscore-as-word-syntax
-      (save-excursion
-        (if (and (not (looking-at "[A-Za-z0-9_$]"))
-                 (looking-back "[A-Za-z0-9_$]"))
-            (setq beg (progn (forward-word -1) (point))
-                  end (progn (forward-word 1) (point)))
-          (setq beg (progn (forward-word 1) (point))
-                end (progn (forward-word -1) (point))))
-        (replace-regexp-in-string
-         "[\"']" ""
-         (buffer-substring-no-properties beg end))))))
-
-(defun js2-mode-forward-sibling ()
-  "Move to the end of the sibling following point in parent.
-Returns non-nil if successful, or nil if there was no following sibling."
-  (let* ((node (js2-node-at-point))
-         (parent (js2-mode-find-enclosing-fn node))
-         sib)
-    (when (setq sib (js2-node-find-child-after (point) parent))
-      (goto-char (+ (js2-node-abs-pos sib)
-                    (js2-node-len sib))))))
-
-(defun js2-mode-backward-sibling ()
-  "Move to the beginning of the sibling node preceding point in parent.
-Parent is defined as the enclosing script or function."
-  (let* ((node (js2-node-at-point))
-         (parent (js2-mode-find-enclosing-fn node))
-         sib)
-    (when (setq sib (js2-node-find-child-before (point) parent))
-      (goto-char (js2-node-abs-pos sib)))))
-
-(defun js2-beginning-of-defun ()
-  "Go to line on which current function starts, and return non-nil.
-If we're not in a function, go to beginning of previous script-level element."
-  (interactive)
-  (let ((parent (js2-node-parent-script-or-fn (js2-node-at-point)))
-        pos sib)
-    (cond
-     ((and (js2-function-node-p parent)
-           (not (eq (point) (setq pos (js2-node-abs-pos parent)))))
-      (goto-char pos))
-     (t
-      (js2-mode-backward-sibling)))))
-
-(defun js2-end-of-defun ()
-  "Go to the char after the last position of the current function.
-If we're not in a function, skips over the next script-level element."
-  (interactive)
-  (let ((parent (js2-node-parent-script-or-fn (js2-node-at-point))))
-    (if (not (js2-function-node-p parent))
-        ;; punt:  skip over next script-level element beyond point
-        (js2-mode-forward-sibling)
-      (goto-char (+ 1 (+ (js2-node-abs-pos parent)
-                         (js2-node-len parent)))))))
-
-(defun js2-mark-defun (&optional allow-extend)
-  "Put mark at end of this function, point at beginning.
-The function marked is the one that contains 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")
-  (let (extended)
-    (when (and allow-extend
-               (or (and (eq last-command this-command) (mark t))
-                   (and transient-mark-mode mark-active)))
-      (let ((sib (save-excursion
-                   (goto-char (mark))
-                   (if (js2-mode-forward-sibling)
-                       (point))))
-            node)
-        (if sib
-            (progn
-              (set-mark sib)
-              (setq extended t))
-          ;; no more siblings - try extending to enclosing node
-          (goto-char (mark t)))))
-   (when (not extended)
-     (let ((node (js2-node-at-point (point) t)) ; skip comments
-           ast fn stmt parent beg end)
-       (when (js2-ast-root-p node)
-         (setq ast node
-               node (or (js2-node-find-child-after (point) node)
-                        (js2-node-find-child-before (point) node))))
-       ;; only mark whole buffer if we can't find any children
-       (if (null node)
-           (setq node ast))
-       (if (js2-function-node-p node)
-           (setq parent node)
-         (setq fn (js2-mode-find-enclosing-fn node)
-               stmt (if (or (null fn)
-                            (js2-ast-root-p fn))
-                        (js2-mode-find-first-stmt node))
-               parent (or stmt fn)))
-       (setq beg (js2-node-abs-pos parent)
-             end (+ beg (js2-node-len parent)))
-       (push-mark beg)
-       (goto-char end)
-       (exchange-point-and-mark)))))
-
-(defun js2-narrow-to-defun ()
-  "Narrow to the function enclosing point."
-  (interactive)
-  (let* ((node (js2-node-at-point (point) t))  ; skip comments
-         (fn (if (js2-script-node-p node)
-                 node
-               (js2-mode-find-enclosing-fn node)))
-         (beg (js2-node-abs-pos fn)))
-    (unless (js2-ast-root-p fn)
-      (narrow-to-region beg (+ beg (js2-node-len fn))))))
-
-(defalias 'js2r 'js2-mode-reset)
-
-(provide 'js2-mode)
-
-;;; js2-mode.el ends here
-
-
-;;; js2.el ends here
deleted file mode 100644
index 80fbe1d8a673c75d3144a03b542080231298bf31..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/.elisp/nose.el
+++ /dev/null
@@ -1,177 +0,0 @@
-;; nose.el --- Easy Python test running in Emacs
-
-;; Copyright (C) 2009 Jason Pellerin, Augie Fackler
-
-;; Licensed under the same terms as Emacs.
-
-;; Version: 0.1.0
-;; Keywords: nose python testing
-;; Created: 04 Apr 2009
-
-;; This file is NOT part of GNU Emacs.
-
-;; Licensed under the same terms as Emacs.
-
-;;; Commentary:
-;; This gives a bunch of functions that handle running nosetests on a
-;; particular buffer or part of a buffer.
-
-;;; Installation
-
-;; In your emacs config:
-;;
-;; (require 'nose)
-;; ; next line only for people with non-eco non-global test runners
-;; ; (add-to-list 'nose-project-names "my/crazy/runner")
-
-;; Note that if your global nose isn't called "nosetests", then you'll want to
-;; redefine nose-global-name to be the command that should be used.
-
-;; By default, the root of a project is found by looking for any of the files
-;; 'setup.py', '.hg' and '.git'. You can add files to check for to the file
-;; list:
-;;
-;; ; (add-to-list 'nose-project-root-files "something")
-
-;; or you can change the project root test to detect in some other way
-;; whether a directory is the project root:
-;;
-;; ; (setq nose-project-root-test (lambda (dirname) (equal dirname "foo")))
-
-;; If you want dots as output, rather than the verbose output:
-;; (defvar nose-use-verbose nil) ; default is t
-
-;; Probably also want some keybindings:
-;; (add-hook 'python-mode-hook
-;;           (lambda ()
-;;             (local-set-key "\C-ca" 'nosetests-all)
-;;             (local-set-key "\C-cm" 'nosetests-module)
-;;             (local-set-key "\C-c." 'nosetests-one)
-;;             (local-set-key "\C-cpa" 'nosetests-pdb-all)
-;;             (local-set-key "\C-cpm" 'nosetests-pdb-module)
-;;             (local-set-key "\C-cp." 'nosetests-pdb-one)))
-
-(defvar nose-project-names '("eco/bin/test"))
-(defvar nose-project-root-files '("setup.py" ".hg" ".git"))
-(defvar nose-project-root-test 'nose-project-root)
-(defvar nose-global-name "nosetests")
-(defvar nose-use-verbose t)
-
-(defun run-nose (&optional tests debug failed)
-  "run nosetests"
-  (let* ((nose (nose-find-test-runner))
-         (where (nose-find-project-root))
-         (args (concat (if debug "--pdb" "")
-                       " "
-                       (if failed "--failed" "")))
-         (tnames (if tests tests "")))
-    (funcall (if debug
-                 'pdb
-               '(lambda (command)
-                  (compilation-start command
-                                     nil
-                                     (lambda (mode) (concat "*nosetests*")))))
-             (format
-              (concat "%s "
-                      (if nose-use-verbose "-v " "")
-                      "%s -w %s -c %ssetup.cfg %s")
-              (nose-find-test-runner) args where where tnames)))
-  )
-
-(defun nosetests-all (&optional debug failed)
-  "run all tests"
-  (interactive)
-  (run-nose nil debug failed))
-
-(defun nosetests-failed (&optional debug)
-  (interactive)
-  (nosetests-all debug t))
-
-(defun nosetests-pdb-all ()
-  (interactive)
-  (nosetests-all t))
-
-(defun nosetests-module (&optional debug)
-  "run nosetests (via eggs/bin/test) on current buffer"
-  (interactive)
-  (run-nose buffer-file-name debug))
-
-(defun nosetests-pdb-module ()
-  (interactive)
-  (nosetests-module t))
-
-(defun nosetests-one (&optional debug)
-  "run nosetests (via eggs/bin/test) on testable thing
- at point in current buffer"
-  (interactive)
-  (run-nose (format "%s:%s" buffer-file-name (nose-py-testable)) debug))
-
-(defun nosetests-pdb-one ()
-  (interactive)
-  (nosetests-one t))
-
-(defun nose-find-test-runner ()
-  (message
-   (let ((result
-          (reduce '(lambda (x y) (or x y))
-        (mapcar 'nose-find-test-runner-names nose-project-names))))
-     (if result
-         result
-       nose-global-name))))
-
-(defun nose-find-test-runner-names (runner)
-  "find eggs/bin/test in a parent dir of current buffer's file"
-  (nose-find-test-runner-in-dir-named
-   (file-name-directory buffer-file-name) runner))
-
-(defun nose-find-test-runner-in-dir-named (dn runner)
-  (let ((fn (expand-file-name runner dn)))
-    (cond ((file-regular-p fn) fn)
-      ((equal dn "/") nil)
-      (t (nose-find-test-runner-in-dir-named
-          (file-name-directory (directory-file-name dn))
-          runner)))))
-
-(defun nose-py-testable ()
-  (let* ((inner-obj (inner-testable))
-         (outer (outer-testable))
-         ;; elisp can't return multiple values
-         (outer-def (car outer))
-         (outer-obj (cdr outer)))
-    (cond ((equal outer-def "def") outer-obj)
-          ((equal inner-obj outer-obj) outer-obj)
-          (t (format "%s.%s" outer-obj inner-obj)))))
-
-(defun inner-testable ()
-  (save-excursion
-    (re-search-backward
-     "^ \\{0,4\\}\\(class\\|def\\)[ \t]+\\([a-zA-Z0-9_]+\\)" nil t)
-    (buffer-substring-no-properties (match-beginning 2) (match-end 2))))
-
-(defun outer-testable ()
-  (save-excursion
-    (re-search-backward
-     "^\\(class\\|def\\)[ \t]+\\([a-zA-Z0-9_]+\\)" nil t)
-    (let ((result
-            (buffer-substring-no-properties (match-beginning 2) (match-end 2))))
-
-      (cons
-       (buffer-substring-no-properties (match-beginning 1) (match-end 1))
-       result))))
-
-(defun nose-find-project-root (&optional dirname)
-  (let ((dn
-         (if dirname
-             dirname
-           (file-name-directory buffer-file-name))))
-    (cond ((funcall nose-project-root-test dn) (expand-file-name dn))
-          ((equal (expand-file-name dn) "/") nil)
-        (t (nose-find-project-root
-             (file-name-directory (directory-file-name dn)))))))
-
-(defun nose-project-root (dirname)
-  (reduce '(lambda (x y) (or x y))
-          (mapcar (lambda (d) (member d (directory-files dirname)))
-                  nose-project-root-files)))
-
-(provide 'nose)
new file mode 100644
--- /dev/null
+++ b/.elisp/package.el
@@ -0,0 +1,1446 @@
+;;; package.el --- Simple package system for Emacs
+
+;; Copyright (C) 2007, 2008, 2009 Tom Tromey <tromey@redhat.com>
+
+;; Author: Tom Tromey <tromey@redhat.com>
+;; Created: 10 Mar 2007
+;; Version: 0.9.4
+;; Keywords: tools
+
+;; This file is not (yet) part of GNU Emacs.
+;; However, it is distributed under the same license.
+
+;; 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, 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; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; To use this, put package.el somewhere on your load-path.  Then add
+;; this to your .emacs:
+;;
+;;    (load "package")
+;;    (package-initialize)
+;;
+;; This will automatically make available the packages you have
+;; installed using package.el.  If your .emacs will refer to these
+;; packages, you may want to initialize the package manager near the
+;; top.
+;;
+;; Note that if you want to be able to automatically download and
+;; install packages from ELPA (the Emacs Lisp Package Archive), then
+;; you will need the 'url' package.  This comes with Emacs 22; Emacs
+;; 21 users will have to find it elsewhere.
+;;
+;; If you installed package.el via the auto-installer:
+;;
+;;    http://tromey.com/elpa/
+;;
+;; then you do not need to edit your .emacs, as the installer will
+;; have done this for you.  The installer will also install the url
+;; package if you need it.
+
+;; Other external functions you may want to use:
+;;
+;; M-x package-list-packages
+;;    Enters a mode similar to buffer-menu which lets you manage
+;;    packages.  You can choose packages for install (mark with "i",
+;;    then "x" to execute) or deletion (not implemented yet), and you
+;;    can see what packages are available.  This will automatically
+;;    fetch the latest list of packages from ELPA.
+;;
+;; M-x package-list-packages-no-fetch
+;;    Like package-list-packages, but does not automatically fetch the
+;;    new list of packages.
+;;
+;; M-x package-install-from-buffer
+;;    Install a package consisting of a single .el file that appears
+;;    in the current buffer.  This only works for packages which
+;;    define a Version header properly; package.el also supports the
+;;    extension headers Package-Version (in case Version is an RCS id
+;;    or similar), and Package-Requires (if the package requires other
+;;    packages).
+;;
+;; M-x package-install-file
+;;    Install a package from the indicated file.  The package can be
+;;    either a tar file or a .el file.  A tar file must contain an
+;;    appropriately-named "-pkg.el" file; a .el file must be properly
+;;    formatted as with package-install-from-buffer.
+
+;; The idea behind package.el is to be able to download packages and
+;; install them.  Packages are versioned and have versioned
+;; dependencies.  Furthermore, this supports built-in packages which
+;; may or may not be newer than user-specified packages.  This makes
+;; it possible to upgrade Emacs and automatically disable packages
+;; which have moved from external to core.  (Note though that we don't
+;; currently register any of these, so this feature does not actually
+;; work.)
+
+;; This code supports a single package repository, ELPA.  All packages
+;; must be registered there.
+
+;; A package is described by its name and version.  The distribution
+;; format is either  a tar file or a single .el file.
+
+;; A tar file should be named "NAME-VERSION.tar".  The tar file must
+;; unpack into a directory named after the package and version:
+;; "NAME-VERSION".  It must contain a file named "PACKAGE-pkg.el"
+;; which consists of a call to define-package.  It may also contain a
+;; "dir" file and the info files it references.
+
+;; A .el file will be named "NAME-VERSION.el" in ELPA, but will be
+;; installed as simply "NAME.el" in a directory named "NAME-VERSION".
+
+;; The downloader will download all dependent packages.  It will also
+;; byte-compile the package's Lisp at install time.
+
+;; At activation time we will set up the load-path and the info path,
+;; and we will load the package's autoloads.  If a package's
+;; dependencies are not available, we will not activate that package.
+
+;; Conceptually a package has multiple state transitions:
+;;
+;; * Download.  Fetching the package from ELPA.
+;; * Install.  Untar the package, or write the .el file, into
+;;   ~/.emacs.d/elpa/ directory.
+;; * Byte compile.  Currently this phase is done during install,
+;;   but we may change this.
+;; * Activate.  Evaluate the autoloads for the package to make it
+;;   available to the user.
+;; * Load.  Actually load the package and run some code from it.
+
+;;; Thanks:
+;;; (sorted by sort-lines):
+
+;; Jim Blandy <jimb@red-bean.com>
+;; Karl Fogel <kfogel@red-bean.com>
+;; Kevin Ryde <user42@zip.com.au>
+;; Lawrence Mitchell
+;; Michael Olson <mwolson@member.fsf.org>
+;; Sebastian Tennant <sebyte@smolny.plus.com>
+;; Stefan Monnier <monnier@iro.umontreal.ca>
+;; Vinicius Jose Latorre <viniciusjl@ig.com.br>
+;; Phil Hagelberg <phil@hagelb.org>
+;; Samuel Bronson <naesten@gmail.com>
+
+;;; History:
+;;
+;; Originally written by Tom Tromey, multiple archive support added by Phil
+;; Hagelberg.
+
+;;; Code:
+
+(defcustom package-archives '(("elpa" . "http://tromey.com/elpa/"))
+  "An alist of archives (names and URLs) from which to fetch.
+The default points to ELPA, the Emacs Lisp Package Archive.
+Note that some code in package.el assumes that this is an http: URL."
+  :type '(alist :key-type (string :tag "Archive name")
+                :value-type (string :tag "Archive URL"))
+  :group 'package
+  :package-version '("package.el" . "0.9.3"))
+
+(defconst package-archive-version 1
+  "Version number of the package archive understood by this file.
+Lower version numbers than this will probably be understood as well.")
+
+(defconst package-el-version "0.9.4"
+  "Version of package.el.")
+
+;; We don't prime the cache since it tends to get out of date.
+(defvar package-archive-contents
+  nil
+  "A representation of the contents of the ELPA archive.
+This is an alist mapping package names (symbols) to package
+descriptor vectors.  These are like the vectors for `package-alist'
+but have extra entries: one which is 'tar for tar packages and
+'single for single-file packages, and one which is the name of
+the archive from which it came.")
+
+(defvar package-user-dir
+  (expand-file-name (convert-standard-filename "~/.emacs.d/elpa"))
+  "Name of the directory where the user's packages are stored.")
+
+(defvar package-directory-list
+  (list (file-name-as-directory package-user-dir)
+        "/usr/share/emacs/site-lisp/elpa/")
+  "List of directories to search for packages.")
+
+(defun package-version-split (string)
+  "Split a package STRING into a version list."
+  (mapcar 'string-to-int (split-string string "[.]")))
+
+(defconst package--builtins-base
+  ;; We use package-version split here to make sure to pick up the
+  ;; minor version.
+  `((emacs . [,(package-version-split emacs-version) nil
+              "GNU Emacs"])
+    (package . [,(package-version-split package-el-version)
+                nil "Simple package system for GNU Emacs"]))
+  "Packages which are always built-in.")
+
+(defvar package--builtins
+  (delq nil
+        (append
+         package--builtins-base
+         (if (>= emacs-major-version 22)
+             ;; FIXME: emacs 22 includes tramp, rcirc, maybe
+             ;; other things...
+             '((erc . [(5 2) nil "An Emacs Internet Relay Chat client"])
+               ;; The external URL is version 1.15, so make sure the
+               ;; built-in one looks newer.
+               (url . [(1 16) nil "URL handling libary"])))
+         (if (>= emacs-major-version 23)
+             '(;; Strangely, nxml-version is missing in Emacs 23.
+               ;; We pick the merge date as the version.
+               (nxml . [(20071123) nil "Major mode for editing XML documents."])
+               (bubbles . [(0 5) nil "Puzzle game for Emacs."])))))
+  "Alist of all built-in packages.
+Maps the package name to a vector [VERSION REQS DOCSTRING].")
+
+(defvar package-alist package--builtins
+  "Alist of all packages available for activation.
+Maps the package name to a vector [VERSION REQS DOCSTRING].")
+
+(defvar package-activated-list
+  (mapcar #'car package-alist)
+  "List of the names of all activated packages.")
+
+(defvar package-obsolete-alist nil
+  "Representation of obsolete packages.
+Like `package-alist', but maps package name to a second alist.
+The inner alist is keyed by version.")
+
+(defun package-version-join (l)
+  "Turn a list L of version numbers into a version string."
+  (mapconcat 'int-to-string l "."))
+
+(defun package--version-first-nonzero (l)
+  "Find the first non-zero number in the list L.
+
+Returns the value of the first non-zero integer in L, or 0 if
+none is found."
+  (while (and l (= (car l) 0))
+    (setq l (cdr l)))
+  (if l (car l) 0))
+
+(defun package-version-compare (v1 v2 fun)
+  "Compare two version V1 and V2 lists according to FUN.
+
+FUN can be <, <=, =, >, >=, or /=."
+  (while (and v1 v2 (= (car v1) (car v2)))
+    (setq v1 (cdr v1)
+          v2 (cdr v2)))
+  (if v1
+      (if v2
+          ;; Both not null; we know the cars are not =.
+          (funcall fun (car v1) (car v2))
+        ;; V1 not null, V2 null.
+        (funcall fun (package--version-first-nonzero v1) 0))
+    (if v2
+        ;; V1 null, V2 not null.
+        (funcall fun 0 (package--version-first-nonzero v2))
+      ;; Both null.
+      (funcall fun 0 0))))
+
+(defun package--test-version-compare ()
+  "Test suite for `package-version-compare'."
+  (unless (and (package-version-compare '(0) '(0) '=)
+               (not (package-version-compare '(1) '(0) '=))
+               (package-version-compare '(1 0 1) '(1) '>=)
+               (package-version-compare '(1 0 1) '(1) '>)
+               (not (package-version-compare '(0 9 1) '(1 0 2) '>=)))
+    (error "Failed"))
+  t)
+
+(defun package-strip-version (dirname)
+  "Strip the version from a combined package name and version.
+E.g., if DIRNAME is \"quux-23.0\", will return \"quux\""
+  (if (string-match "^\\(.*\\)-[0-9]+\\([.][0-9]+\\)*$" dirname)
+      (match-string 1 dirname)))
+
+(defun package-load-descriptor (dir package)
+  "Load the description file in directory DIR for a PACKAGE.
+Return nil if the package could not be found."
+  (let* ((pkg-dir (expand-file-name package dir))
+         (pkg-file (expand-file-name
+                    (concat (package-strip-version package) "-pkg") pkg-dir)))
+    (when (and (file-directory-p pkg-dir)
+               (file-exists-p (concat pkg-file ".el")))
+        (load pkg-file nil t))))
+
+(defun package-load-all-descriptors ()
+  "Load descriptors of all packages.
+Uses `package-directory-list' to find packages."
+  (mapc (lambda (dir)
+          (if (file-directory-p dir)
+              (mapc (lambda (name)
+                      (package-load-descriptor dir name))
+                    (directory-files dir nil "^[^.]"))))
+        package-directory-list))
+
+(defsubst package-desc-vers (desc)
+  "Extract version from a package description vector DESC."
+  (aref desc 0))
+
+(defsubst package-desc-reqs (desc)
+  "Extract requirements from a package description vector DESC."
+  (aref desc 1))
+
+(defsubst package-desc-doc (desc)
+  "Extract doc string from a package description vector DESC."
+  (aref desc 2))
+
+(defsubst package-desc-kind (desc)
+  "Extract the kind of download from an archive package description vector DESC."
+  (aref desc 3))
+
+(defun package-do-activate (package pkg-vec)
+  "Set up a single PACKAGE.
+
+Modifies `load-path' to include the package directory and loads
+the `autoload' file for the package. PKG-VEC is the package info
+as retrieved from the package mirror."
+  (let* ((pkg-name (symbol-name package))
+         (pkg-ver-str (package-version-join (package-desc-vers pkg-vec)))
+         (dir-list package-directory-list)
+         (pkg-dir))
+    (while dir-list
+      (let ((subdir (concat (car dir-list) pkg-name "-" pkg-ver-str "/")))
+        (if (file-directory-p subdir)
+            (progn
+              (setq pkg-dir subdir)
+              (setq dir-list nil))
+          (setq dir-list (cdr dir-list)))))
+    (unless pkg-dir
+      (error "Internal error: could not find directory for %s-%s"
+             pkg-name pkg-ver-str))
+    (if (file-exists-p (concat pkg-dir "dir"))
+        (progn
+          ;; FIXME: not the friendliest, but simple.
+          (require 'info)
+          (info-initialize)
+          (setq Info-directory-list (cons pkg-dir Info-directory-list))))
+    (setq load-path (cons pkg-dir load-path))
+    ;; Load the autoloads and activate the package.
+    (load (concat pkg-dir (symbol-name package) "-autoloads")
+          nil t)
+    (setq package-activated-list (cons package package-activated-list))
+    ;; Don't return nil.
+    t))
+
+(defun package--built-in (package version)
+  "Return true if PACKAGE at VERSION is built-in to Emacs."
+  (let ((elt (assq package package--builtins)))
+    (and elt
+         (package-version-compare (package-desc-vers (cdr elt)) version '=))))
+
+;; FIXME: return a reason instead?
+(defun package-activate (package version)
+  "Try to activate PACKAGE at version VERSION.
+Return nil if the package could not be activated.
+Recursively activates all dependencies of the named package."
+  ;; Assume the user knows what he is doing -- go ahead and activate a
+  ;; newer version of a package if an older one has already been
+  ;; activated.  This is not ideal; we'd at least need to check to see
+  ;; if the package has actually been loaded, and not merely
+  ;; activated.  However, don't try to activate 'emacs', as that makes
+  ;; no sense.
+  (unless (eq package 'emacs)
+    (let* ((pkg-desc (assq package package-alist))
+           (this-version (package-desc-vers (cdr pkg-desc)))
+           (req-list (package-desc-reqs (cdr pkg-desc)))
+           ;; If the package was never activated, we want to do it
+           ;; now.
+           (keep-going (or (not (memq package package-activated-list))
+                           (package-version-compare this-version version '>))))
+      (while (and req-list keep-going)
+        (or (package-activate (car (car req-list))
+                              (car (cdr (car req-list))))
+            (setq keep-going nil))
+        (setq req-list (cdr req-list)))
+      (if keep-going
+          (package-do-activate package (cdr pkg-desc))
+        ;; We get here if a dependency failed to activate -- but we
+        ;; can also get here if the requested package was already
+        ;; activated.  Return non-nil in the latter case.
+        (and (memq package package-activated-list)
+             (package-version-compare this-version version '>=))))))
+
+(defun package-mark-obsolete (package pkg-vec)
+  "Put PACKAGE on the obsolete list, if not already there.
+
+PKG-VEC describes the version of PACKAGE to mark obsolete."
+  (let ((elt (assq package package-obsolete-alist)))
+    (if elt
+        ;; If this obsolete version does not exist in the list, update
+        ;; it the list.
+        (unless (assoc (package-desc-vers pkg-vec) (cdr elt))
+          (setcdr elt (cons (cons (package-desc-vers pkg-vec) pkg-vec)
+                            (cdr elt))))
+      ;; Make a new association.
+      (setq package-obsolete-alist
+            (cons (cons package (list (cons (package-desc-vers pkg-vec)
+                                            pkg-vec)))
+                  package-obsolete-alist)))))
+
+;; (define-package "emacs" "21.4.1" "GNU Emacs core package.")
+;; (define-package "erc" "5.1" "ERC - irc client" '((emacs "21.0")))
+(defun define-package (name-str version-string
+                                &optional docstring requirements)
+  "Define a new package.
+NAME-STR is the name of the package, a string.
+VERSION-STRING is the version of the package, a dotted sequence
+of integers.
+DOCSTRING is the optional description.
+REQUIREMENTS is a list of requirements on other packages.
+Each requirement is of the form (OTHER-PACKAGE \"VERSION\")."
+  (let* ((name (intern name-str))
+         (pkg-desc (assq name package-alist))
+         (new-version (package-version-split version-string))
+         (new-pkg-desc
+          (cons name
+                (vector new-version
+                        (mapcar
+                         (lambda (elt)
+                           (list (car elt)
+                                 (package-version-split (car (cdr elt)))))
+                         requirements)
+                        docstring))))
+    ;; Only redefine a package if the redefinition is newer.
+    (if (or (not pkg-desc)
+            (package-version-compare new-version
+                                     (package-desc-vers (cdr pkg-desc))
+                                     '>))
+        (progn
+          (when pkg-desc
+            ;; Remove old package and declare it obsolete.
+            (setq package-alist (delq pkg-desc package-alist))
+            (package-mark-obsolete (car pkg-desc) (cdr pkg-desc)))
+          ;; Add package to the alist.
+          (setq package-alist (cons new-pkg-desc package-alist)))
+      ;; You can have two packages with the same version, for instance
+      ;; one in the system package directory and one in your private
+      ;; directory.  We just let the first one win.
+      (unless (package-version-compare new-version
+                                       (package-desc-vers (cdr pkg-desc))
+                                       '=)
+        ;; The package is born obsolete.
+        (package-mark-obsolete (car new-pkg-desc) (cdr new-pkg-desc))))))
+
+;; From Emacs 22.
+(defun package-autoload-ensure-default-file (file)
+  "Make sure that the autoload file FILE exists and if not create it."
+  (unless (file-exists-p file)
+    (write-region
+     (concat ";;; " (file-name-nondirectory file)
+             " --- automatically extracted autoloads\n"
+             ";;\n"
+             ";;; Code:\n\n"
+             "\n;; Local Variables:\n"
+             ";; version-control: never\n"
+             ";; no-byte-compile: t\n"
+             ";; no-update-autoloads: t\n"
+             ";; End:\n"
+             ";;; " (file-name-nondirectory file)
+             " ends here\n")
+     nil file))
+  file)
+
+(defun package-generate-autoloads (name pkg-dir)
+  "Generate autoload definitions for package NAME in PKG-DIR."
+  (let* ((auto-name (concat name "-autoloads.el"))
+         (ignore-name (concat name "-pkg.el"))
+         (generated-autoload-file (concat pkg-dir auto-name))
+         (version-control 'never))
+    ;; In Emacs 22 `update-directory-autoloads' does not seem
+    ;; to be autoloaded...
+    (require 'autoload)
+    (unless (fboundp 'autoload-ensure-default-file)
+      (package-autoload-ensure-default-file generated-autoload-file))
+    (update-directory-autoloads pkg-dir)))
+
+(defun package-untar-buffer ()
+  "Untar the current buffer.
+This uses `tar-untar-buffer' if it is available.
+Otherwise it uses an external `tar' program.
+`default-directory' should be set by the caller."
+  (require 'tar-mode)
+  (if (fboundp 'tar-untar-buffer)
+      (progn
+        ;; tar-mode messes with narrowing, so we just let it have the
+        ;; whole buffer to play with.
+        (delete-region (point-min) (point))
+        (tar-mode)
+        (tar-untar-buffer))
+    ;; FIXME: check the result.
+    (call-process-region (point) (point-max) "tar" nil '(nil nil) nil
+                         "xf" "-")))
+
+(defun package-unpack (name version)
+  "Unpack a package tar from the current buffer.
+
+Unpack the package, using NAME and VERSION to determine the
+target. The current buffer is expected to contain a tarred
+package archive."
+  (let ((pkg-dir (concat (file-name-as-directory package-user-dir)
+                         (symbol-name name) "-" version "/")))
+    ;; Be careful!!
+    (make-directory package-user-dir t)
+    (if (file-directory-p pkg-dir)
+        (mapc (lambda (file) nil) ; 'delete-file -- FIXME: when we're
+                                        ; more confident
+              (directory-files pkg-dir t "^[^.]")))
+    (let* ((default-directory (file-name-as-directory package-user-dir)))
+      (package-untar-buffer)
+      (package-generate-autoloads (symbol-name name) pkg-dir)
+      (let ((load-path (cons pkg-dir load-path)))
+        (byte-recompile-directory pkg-dir 0 t)))))
+
+(defun package-unpack-single (file-name version desc requires)
+  "Install the contents of the current buffer as a package.
+
+FILE-NAME is the name of the current file being unpacked.
+package.el itself is handled specially, so this information is
+important.
+
+VERSION is the version (as a string) of the file being unpacked.
+
+DESC is a brief description of the package.
+
+REQUIRES is a list of symbols which this package needs to run."
+  (let* ((dir (file-name-as-directory package-user-dir)))
+    ;; Special case "package".
+    (if (string= file-name "package")
+        (write-region (point-min) (point-max) (concat dir file-name ".el")
+                      nil nil nil nil)
+      (let ((pkg-dir (file-name-as-directory
+                      (concat dir file-name "-" version))))
+        (make-directory pkg-dir t)
+        (write-region (point-min) (point-max)
+                      (concat pkg-dir file-name ".el")
+                      nil nil nil 'excl)
+        (let ((print-level nil)
+              (print-length nil))
+          (write-region
+           (concat
+            (prin1-to-string
+             (list 'define-package
+                   file-name
+                   version
+                   desc
+                   (list 'quote
+                         ;; Turn version lists into string form.
+                         (mapcar
+                          (lambda (elt)
+                            (list (car elt)
+                                  (package-version-join (car (cdr elt)))))
+                          requires))))
+            "\n")
+           nil
+           (concat pkg-dir file-name "-pkg.el")
+           nil nil nil 'excl))
+        (package-generate-autoloads file-name pkg-dir)
+        (let ((load-path (cons pkg-dir load-path)))
+          (byte-recompile-directory pkg-dir 0 t))))))
+
+(defun package-handle-response ()
+  "Handle the response from the server.
+Parse the HTTP response and throw if an error occurred.
+The url package seems to require extra processing for this.
+This should be called in a `save-excursion', in the download buffer.
+It will move point to somewhere in the headers."
+  (let ((type (url-type url-current-object)))
+    (cond
+     ((equal type "http")
+      (let ((response (url-http-parse-response)))
+        (when (or (< response 200) (>= response 300))
+          (display-buffer (current-buffer))
+          (error "Error during download request:%s"
+                 (buffer-substring-no-properties (point) (progn
+                                                           (end-of-line)
+                                                           (point)))))))
+     ((equal type "file")
+      nil))))
+
+(defun package-download-single (name version desc requires)
+  "Download and install a single-file package.
+
+NAME, VERSION, DESC, and REQUIRES are used to build the package
+info."
+  (let ((buffer (url-retrieve-synchronously
+                 (concat (package-archive-for name)
+                         (symbol-name name) "-" version ".el"))))
+    (save-excursion
+      (set-buffer buffer)
+      (package-handle-response)
+      (re-search-forward "^$" nil 'move)
+      (forward-char)
+      (delete-region (point-min) (point))
+      (package-unpack-single (symbol-name name) version desc requires)
+      (kill-buffer buffer))))
+
+(defun package-download-tar (name version)
+  "Download and install a tar package NAME at VERSION."
+  (let ((tar-buffer (url-retrieve-synchronously
+                     (concat (package-archive-for name)
+                             (symbol-name name) "-" version ".tar"))))
+    (save-excursion
+      (set-buffer tar-buffer)
+      (package-handle-response)
+
+      ;; Skip past url-retrieve headers, which would otherwise confuse poor
+      ;; tar-mode.
+      (goto-char (point-min))
+      (re-search-forward "^$" nil 'move)
+      (forward-char)
+
+      (package-unpack name version)
+      (kill-buffer tar-buffer))))
+
+(defun package-installed? (package &optional min-version)
+  "Check whether PACKAGE is installed and at least MIN-VERSION."
+  (let ((pkg-desc (assq package package-alist)))
+    (and pkg-desc
+         (package-version-compare min-version
+                                  (package-desc-vers (cdr pkg-desc))
+                                  '<=))))
+
+(defun package-compute-transaction (result requirements)
+  "Recursively prepare a transaction, resolving dependencies.
+
+RESULT is a flattened list of packages to install.
+`package-compute-transaction' recursively builds this argument
+before passing it up to the caller.
+
+REQUIREMENTS is a list of required packages, to be recursively
+processed to resolve all dependencies (if possible)."
+  (while requirements
+    (let* ((elt (car requirements))
+           (next-pkg (car elt))
+           (next-version (car (cdr elt))))
+      (unless (package-installed? next-pkg next-version)
+        (let ((pkg-desc (assq next-pkg package-archive-contents)))
+          (unless pkg-desc
+            (error "Package '%s' not available for installation"
+                   (symbol-name next-pkg)))
+          (unless (package-version-compare (package-desc-vers (cdr pkg-desc))
+                                           next-version
+                                           '>=)
+            (error
+             "Need package '%s' with version %s, but only %s is available"
+             (symbol-name next-pkg) (package-version-join next-version)
+             (package-version-join (package-desc-vers (cdr pkg-desc)))))
+          ;; Only add to the transaction if we don't already have it.
+          (unless (memq next-pkg result)
+            (setq result (cons next-pkg result)))
+          (setq result
+                (package-compute-transaction result
+                                             (package-desc-reqs
+                                              (cdr pkg-desc)))))))
+    (setq requirements (cdr requirements)))
+  result)
+
+(defun package-read-from-string (str)
+  "Read a Lisp expression from STR.
+Signal an error if the entire string was not used."
+  (let* ((read-data (read-from-string str))
+         (more-left
+          (condition-case nil
+              ;; The call to `ignore' suppresses a compiler warning.
+              (progn (ignore (read-from-string
+                              (substring str (cdr read-data))))
+                     t)
+            (end-of-file nil))))
+    (if more-left
+        (error "Can't read whole string")
+      (car read-data))))
+
+(defun package--read-archive-file (file)
+  "Re-read archive file FILE, if it exists.
+Will return the data from the file, or nil if the file does not exist.
+Will throw an error if the archive version is too new."
+  (let ((filename (concat (file-name-as-directory package-user-dir)
+                          file)))
+    (if (file-exists-p filename)
+        (with-temp-buffer
+          (insert-file-contents-literally filename)
+          (let ((contents (package-read-from-string
+                           (buffer-substring-no-properties (point-min)
+                                                           (point-max)))))
+            (if (> (car contents) package-archive-version)
+                (error "Package archive version %d is greater than %d - upgrade package.el"
+                       (car contents) package-archive-version))
+            (cdr contents))))))
+
+(defun package-read-all-archive-contents ()
+  "Read the archive description of each of the archives in `package-archives'."
+  (dolist (archive package-archives)
+    (package-read-archive-contents (car archive)))
+  (let ((builtins (package--read-archive-file
+                   (concat "archives/" (caar package-archives)
+                           "/builtin-packages"))))
+    (if builtins
+        ;; Version 1 of 'builtin-packages' is a list where the car is
+        ;; a split emacs version and the cdr is an alist suitable for
+        ;; package--builtins.
+        (let ((our-version (package-version-split emacs-version))
+              (result package--builtins-base))
+          (setq package--builtins
+                (dolist (elt builtins result)
+                  (if (package-version-compare our-version (car elt) '>=)
+                      (setq result (append (cdr elt) result)))))))))
+
+(defun package-read-archive-contents (archive)
+  "Re-read `archive-contents' and `builtin-packages', for ARCHIVE if they exist.
+
+Will set `package-archive-contents' and `package--builtins' if
+successful. Will throw an error if the archive version is too
+new."
+  (let ((archive-contents (package--read-archive-file
+                           (concat "archives/" archive
+                                   "/archive-contents"))))
+    (if archive-contents
+        ;; Version 1 of 'archive-contents' is identical to our
+        ;; internal representation.
+        ;; TODO: merge archive lists
+        (dolist (package archive-contents)
+          (package--add-to-archive-contents package archive)))))
+
+(defun package--add-to-archive-contents (package archive)
+  "Add the PACKAGE from the given ARCHIVE if needed.
+
+Adds the archive from which it came to the end of the package vector."
+  (let* ((package-name (car package))
+         (package-version (aref (cdr package) 0))
+         (package-with-archive (cons (car package)
+                                     (vconcat (cdr package) (vector archive))))
+         (existing-package (cdr (assq package-name package-archive-contents))))
+    (when (or (not existing-package)
+              (package-version-compare package-version
+                                       (aref existing-package 0) '>))
+      (add-to-list 'package-archive-contents package-with-archive))))
+
+(defun package-download-transaction (transaction)
+  "Download and install all the packages in the given TRANSACTION."
+  (mapc (lambda (elt)
+          (let* ((desc (cdr (assq elt package-archive-contents)))
+                 (v-string (package-version-join (package-desc-vers desc)))
+                 (kind (package-desc-kind desc)))
+            (cond
+             ((eq kind 'tar)
+              (package-download-tar elt v-string))
+             ((eq kind 'single)
+              (package-download-single elt v-string
+                                       (package-desc-doc desc)
+                                       (package-desc-reqs desc)))
+             (t
+              (error "Unknown package kind: " (symbol-name kind))))))
+        transaction))
+
+(defun package-install (name)
+  "Install the package named NAME.
+Interactively, prompts for the package name."
+  (interactive
+   (list (progn
+           (intern (completing-read "Install package: "
+                                    (mapcar (lambda (elt)
+                                              (cons (symbol-name (car elt))
+                                                    nil))
+                                            package-archive-contents)
+                                    nil t)))))
+  (let ((pkg-desc (assq name package-archive-contents)))
+    (unless pkg-desc
+      (error "Package '%s' not available for installation"
+             (symbol-name name)))
+    (let ((transaction
+           (package-compute-transaction (list name)
+                                        (package-desc-reqs (cdr pkg-desc)))))
+      (package-download-transaction transaction)))
+  ;; Try to activate it.
+  (package-initialize))
+
+(defun package-strip-rcs-id (v-str)
+  "Strip RCS version ID from the version string V-STR.
+
+If the result looks like a dotted numeric version, return it.
+Otherwise return nil."
+  (if v-str
+      (if (string-match "[ \t]*\\$\\(?:Revision\\|Id\\):[ \t]\\(?:[^ \t]+,v[ \t]+\\)?\\([0-9.]+\\).*\\$$" v-str)
+          (match-string 1 v-str)
+        (if (string-match "^[0-9.]*$" v-str)
+            v-str))))
+
+(defun package-buffer-info ()
+  "Return a vector of information about the package in the current buffer.
+The vector looks like [FILENAME REQUIRES DESCRIPTION VERSION COMMENTARY]
+FILENAME is the file name, a string.  It does not have the \".el\" extension.
+REQUIRES is a requires list, or nil.
+DESCRIPTION is the package description (a string).
+VERSION is the version, a string.
+COMMENTARY is the commentary section, a string, or nil if none.
+Throws an exception if the buffer does not contain a conforming package.
+If there is a package, narrows the buffer to the file's boundaries.
+May narrow buffer or move point even on failure."
+  (goto-char (point-min))
+  (if (re-search-forward "^;;; \\([^ ]*\\)\\.el --- \\(.*\\)$" nil t)
+      (let ((file-name (match-string 1))
+            (desc (match-string 2))
+            (start (progn (beginning-of-line) (point))))
+        (if (search-forward (concat ";;; " file-name ".el ends here"))
+            (progn
+              ;; Try to include a trailing newline.
+              (forward-line)
+              (narrow-to-region start (point))
+              (require 'lisp-mnt)
+              ;; Use some headers we've invented to drive the process.
+              (let* ((requires-str (lm-header "package-requires"))
+                     (requires (if requires-str
+                                   (package-read-from-string requires-str)))
+                     ;; Prefer Package-Version, because if it is
+                     ;; defined the package author probably wants us
+                     ;; to use it.  Otherwise try Version.
+                     (pkg-version
+                      (or (package-strip-rcs-id (lm-header "package-version"))
+                          (package-strip-rcs-id (lm-header "version"))))
+                     (commentary (lm-commentary)))
+                (unless pkg-version
+                  (error
+                   "Package does not define a usable \"Version\" or \"Package-Version\" header"))
+                ;; Turn string version numbers into list form.
+                (setq requires
+                      (mapcar
+                       (lambda (elt)
+                         (list (car elt)
+                               (package-version-split (car (cdr elt)))))
+                       requires))
+                (set-text-properties 0 (length file-name) nil file-name)
+                (set-text-properties 0 (length pkg-version) nil pkg-version)
+                (set-text-properties 0 (length desc) nil desc)
+                (vector file-name requires desc pkg-version commentary)))
+          (error "Package missing a terminating comment")))
+    (error "No starting comment for package")))
+
+(defun package-tar-file-info (file)
+  "Find package information for a tar file.
+FILE is the name of the tar file to examine.
+The return result is a vector like `package-buffer-info'."
+  (setq file (expand-file-name file))
+  (unless (string-match "^\\(.+\\)-\\([0-9.]+\\)\\.tar$" file)
+    (error "`%s' doesn't have a package-ish name" file))
+  (let* ((pkg-name (file-name-nondirectory (match-string-no-properties 1 file)))
+         (pkg-version (match-string-no-properties 2 file))
+         ;; Extract the package descriptor.
+         (pkg-def-contents (shell-command-to-string
+                            ;; Requires GNU tar.
+                            (concat "tar -xOf " file " "
+                                    pkg-name "-" pkg-version "/"
+                                    pkg-name "-pkg.el")))
+         (pkg-def-parsed (package-read-from-string pkg-def-contents)))
+    (unless (eq (car pkg-def-parsed) 'define-package)
+      (error "%s-pkg.el doesn't contain `define-package' sexp" pkg-name))
+    (let ((name-str (nth 1 pkg-def-parsed))
+          (version-string (nth 2 pkg-def-parsed))
+          (docstring (nth 3 pkg-def-parsed))
+          (requires (nth 4 pkg-def-parsed))
+
+          (readme (shell-command-to-string
+                   ;; Requires GNU tar.
+                   (concat "tar -xOf " file " "
+                           pkg-name "-" pkg-version "/README"))))
+      (unless (equal pkg-version version-string)
+        (error "Inconsistent versions!"))
+      (unless (equal pkg-name name-str)
+        (error "Inconsistent names!"))
+      ;; Kind of a hack.
+      (if (string-match ": Not found in archive" readme)
+          (setq readme nil))
+      ;; Turn string version numbers into list form.
+      (if (eq (car requires) 'quote)
+          (setq requires (car (cdr requires))))
+      (setq requires
+            (mapcar
+             (lambda (elt)
+               (list (car elt)
+                     (package-version-split (car (cdr elt)))))
+             requires))
+      (vector pkg-name requires docstring version-string readme))))
+
+(defun package-install-buffer-internal (pkg-info type)
+  "Download and install a single package.
+
+PKG-INFO describes the package to be installed.
+
+TYPE is either `single' or `tar'."
+  (save-excursion
+    (save-restriction
+      (let* ((file-name (aref pkg-info 0))
+             (requires (aref pkg-info 1))
+             (desc (if (string= (aref pkg-info 2) "")
+                       "No description available."
+                     (aref pkg-info 2)))
+             (pkg-version (aref pkg-info 3)))
+        ;; Download and install the dependencies.
+        (let ((transaction (package-compute-transaction nil requires)))
+          (package-download-transaction transaction))
+        ;; Install the package itself.
+        (cond
+         ((eq type 'single)
+          (package-unpack-single file-name pkg-version desc requires))
+         ((eq type 'tar)
+          (package-unpack (intern file-name) pkg-version))
+         (t
+          (error "Unknown type: %s" (symbol-name type))))
+        ;; Try to activate it.
+        (package-initialize)))))
+
+(defun package-install-from-buffer ()
+  "Install a package from the current buffer.
+The package is assumed to be a single .el file which
+follows the elisp comment guidelines; see
+info node `(elisp)Library Headers'."
+  (interactive)
+  (package-install-buffer-internal (package-buffer-info) 'single))
+
+(defun package-install-file (file)
+  "Install a package from a FILE.
+The file can either be a tar file or an Emacs Lisp file."
+  (interactive "fPackage file name: ")
+  (with-temp-buffer
+    (insert-file-contents-literally file)
+    (cond
+     ((string-match "\\.el$" file) (package-install-from-buffer))
+     ((string-match "\\.tar$" file)
+      (package-install-buffer-internal (package-tar-file-info file) 'tar))
+     (t (error "Unrecognized extension `%s'" (file-name-extension file))))))
+
+(defun package-delete (name version)
+  "Delete package NAME at VERSION."
+  (require 'dired)          ; for dired-delete-file
+  (dired-delete-file (concat (file-name-as-directory package-user-dir)
+                             name "-" version)
+                     ;; FIXME: query user?
+                     'always))
+
+(defun package--encode (string)
+  "Encode a STRING by replacing some characters with XML entities."
+  ;; We need a special case for translating "&" to "&amp;".
+  (let ((index))
+    (while (setq index (string-match "[&]" string index))
+      (setq string (replace-match "&amp;" t nil string))
+      (setq index (1+ index))))
+  (while (string-match "[<]" string)
+    (setq string (replace-match "&lt;" t nil string)))
+  (while (string-match "[>]" string)
+    (setq string (replace-match "&gt;" t nil string)))
+  (while (string-match "[']" string)
+    (setq string (replace-match "&apos;" t nil string)))
+  (while (string-match "[\"]" string)
+    (setq string (replace-match "&quot;" t nil string)))
+  string)
+
+(defun package--update-file (file location text)
+  "Update FILE by finding LOCATION and inserting TEXT."
+  (save-excursion
+    (let ((old-buffer (find-buffer-visiting file)))
+      (with-current-buffer (let ((find-file-visit-truename t))
+                             (or old-buffer (find-file-noselect file)))
+        (goto-char (point-min))
+        (search-forward location)
+        (forward-line)
+        (insert text)
+        (let ((file-precious-flag t))
+          (save-buffer))
+        (unless old-buffer
+          (kill-buffer (current-buffer)))))))
+
+(defun package-archive-for (name)
+  "Return the archive containing the package NAME."
+  (let ((desc (cdr (assq (intern-soft name) package-archive-contents))))
+    (cdr (assoc (aref desc (- (length desc) 1)) package-archives))))
+
+(defun package--download-one-archive (archive file)
+  "Download a single archive file and cache it locally.
+
+Downloads the archive index from ARCHIVE and stores it in FILE."
+  (let* ((archive-name (car archive))
+         (archive-url (cdr archive))
+         (buffer (url-retrieve-synchronously (concat archive-url file))))
+    (save-excursion
+      (set-buffer buffer)
+      (package-handle-response)
+      (re-search-forward "^$" nil 'move)
+      (forward-char)
+      (delete-region (point-min) (point))
+      (make-directory (concat (file-name-as-directory package-user-dir)
+                              "archives/" archive-name) t)
+      (setq buffer-file-name (concat (file-name-as-directory package-user-dir)
+                                     "archives/" archive-name "/" file))
+      (let ((version-control 'never))
+        (save-buffer))
+      (kill-buffer buffer))))
+
+(defun package-refresh-contents ()
+  "Download the ELPA archive description if needed.
+Invoking this will ensure that Emacs knows about the latest versions
+of all packages.  This will let Emacs make them available for
+download."
+  (interactive)
+  (dolist (archive package-archives)
+    (package--download-one-archive archive "archive-contents"))
+  (package-read-all-archive-contents))
+
+(defun package-initialize ()
+  "Load all packages and activate as many as possible."
+  (setq package-obsolete-alist nil)
+  (package-load-all-descriptors)
+  (package-read-all-archive-contents)
+  ;; Try to activate all our packages.
+  (mapc (lambda (elt)
+          (package-activate (car elt) (package-desc-vers (cdr elt))))
+        package-alist))
+
+
+
+;;;; Package menu mode.
+
+(defvar package-menu-mode-map
+  (let ((map (make-keymap))
+	(menu-map (make-sparse-keymap "Package")))
+    (suppress-keymap map)
+    (define-key map "q" 'quit-window)
+    (define-key map "n" 'next-line)
+    (define-key map "p" 'previous-line)
+    (define-key map "u" 'package-menu-mark-unmark)
+    (define-key map "\177" 'package-menu-backup-unmark)
+    (define-key map "d" 'package-menu-mark-delete)
+    (define-key map "i" 'package-menu-mark-install)
+    (define-key map "g" 'package-menu-revert)
+    (define-key map "r" 'package-menu-refresh)
+    (define-key map "~" 'package-menu-mark-obsolete-for-deletion)
+    (define-key map "x" 'package-menu-execute)
+    (define-key map "h" 'package-menu-quick-help)
+    (define-key map "?" 'package-menu-view-commentary)
+    (define-key map [menu-bar package-menu] (cons "Package" menu-map))
+    (define-key menu-map [mq]
+      '(menu-item "Quit" quit-window
+		  :help "Quit package selection"))
+    (define-key menu-map [s1] '("--"))
+    (define-key menu-map [mn]
+      '(menu-item "Next" next-line
+		  :help "Next Line"))
+    (define-key menu-map [mp]
+      '(menu-item "Previous" previous-line
+		  :help "Previous Line"))
+    (define-key menu-map [s2] '("--"))
+    (define-key menu-map [mu]
+      '(menu-item "Unmark" package-menu-mark-unmark
+		  :help "Clear any marks on a package and move to the next line"))
+    (define-key menu-map [munm]
+      '(menu-item "Unmark backwards" package-menu-backup-unmark
+		  :help "Back up one line and clear any marks on that package"))
+    (define-key menu-map [md]
+      '(menu-item "Mark for deletion" package-menu-mark-delete
+		  :help "Mark a package for deletion and move to the next line"))
+    (define-key menu-map [mi]
+      '(menu-item "Mark for install" package-menu-mark-install
+		  :help "Mark a package for installation and move to the next line"))
+    (define-key menu-map [s3] '("--"))
+    (define-key menu-map [mg]
+      '(menu-item "Update package list" package-menu-revert
+		  :help "Update the list of packages"))
+    (define-key menu-map [mr]
+      '(menu-item "Refresh package list" package-menu-refresh
+		  :help "Download the ELPA archive"))
+    (define-key menu-map [s4] '("--"))
+    (define-key menu-map [mt]
+      '(menu-item "Mark obsolete packages" package-menu-mark-obsolete-for-deletion
+		  :help "Mark all obsolete packages for deletion"))
+    (define-key menu-map [mx]
+      '(menu-item "Execute actions" package-menu-execute
+		  :help "Perform all the marked actions"))
+    (define-key menu-map [s5] '("--"))
+    (define-key menu-map [mh]
+      '(menu-item "Help" package-menu-quick-help
+		  :help "Show short key binding help for package-menu-mode"))
+    (define-key menu-map [mc]
+      '(menu-item "View Commentary" package-menu-view-commentary
+		  :help "Display information about this package"))
+    map)
+   "Local keymap for `package-menu-mode' buffers.")
+
+(defvar package-menu-sort-button-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [header-line mouse-1] 'package-menu-sort-by-column)
+    (define-key map [follow-link] 'mouse-face)
+    map)
+  "Local keymap for package menu sort buttons.")
+
+(put 'package-menu-mode 'mode-class 'special)
+
+(defun package-menu-mode ()
+  "Major mode for browsing a list of packages.
+Letters do not insert themselves; instead, they are commands.
+\\<package-menu-mode-map>
+\\{package-menu-mode-map}"
+  (kill-all-local-variables)
+  (use-local-map package-menu-mode-map)
+  (setq major-mode 'package-menu-mode)
+  (setq mode-name "Package Menu")
+  (setq truncate-lines t)
+  (setq buffer-read-only t)
+  ;; Support Emacs 21.
+  (if (fboundp 'run-mode-hooks)
+      (run-mode-hooks 'package-menu-mode-hook)
+    (run-hooks 'package-menu-mode-hook)))
+
+(defun package-menu-refresh ()
+  "Download the ELPA archive.
+This fetches the file describing the current contents of
+the Emacs Lisp Package Archive, and then refreshes the
+package menu.  This lets you see what new packages are
+available for download."
+  (interactive)
+  (package-refresh-contents)
+  (package-list-packages-internal))
+
+(defun package-menu-revert ()
+  "Update the list of packages."
+  (interactive)
+  (package-list-packages-internal))
+
+(defun package-menu-mark-internal (what)
+  "Internal function to mark a package.
+
+WHAT is the character used to mark the line."
+  (unless (eobp)
+    (let ((buffer-read-only nil))
+      (beginning-of-line)
+      (delete-char 1)
+      (insert what)
+      (forward-line))))
+
+(defun package-menu-mark-delete (&optional arg)
+  "Mark a package for deletion and move to the next line.
+
+ARG is a (currently unused) numeric argument."
+  (interactive "p")
+  (package-menu-mark-internal "D"))
+
+(defun package-menu-mark-install (&optional arg)
+  "Mark a package for installation and move to the next line.
+
+ARG is a (currently unused) numeric argument."
+  (interactive "p")
+  (package-menu-mark-internal "I"))
+
+(defun package-menu-mark-unmark (&optional arg)
+  "Clear any marks on a package and move to the next line.
+
+ARG is a (currently unused) numeric argument."
+  (interactive "p")
+  (package-menu-mark-internal " "))
+
+(defun package-menu-backup-unmark ()
+  "Back up one line and clear any marks on that package."
+  (interactive)
+  (forward-line -1)
+  (package-menu-mark-internal " ")
+  (forward-line -1))
+
+(defun package-menu-mark-obsolete-for-deletion ()
+  "Mark all obsolete packages for deletion."
+  (interactive)
+  (save-excursion
+    (goto-char (point-min))
+    (forward-line 2)
+    (while (not (eobp))
+      (if (looking-at ".*\\s obsolete\\s ")
+          (package-menu-mark-internal "D")
+        (forward-line 1)))))
+
+(defun package-menu-quick-help ()
+  "Show short key binding help for `package-menu-mode'."
+  (interactive)
+  (message "n-ext, i-nstall, d-elete, u-nmark, x-ecute, r-efresh, h-elp ?-view commentary"))
+
+(defun package-menu-view-commentary ()
+  "Display information about this package.
+For single-file packages, shows the commentary section from the header.
+For larger packages, shows the README file."
+  (interactive)
+  (let* (start-point ok
+                     (pkg-name (package-menu-get-package))
+                     (buffer (url-retrieve-synchronously
+                              (concat (package-archive-for pkg-name)
+                                      pkg-name "-readme.txt"))))
+    (with-current-buffer buffer
+      ;; FIXME: it would be nice to work with any URL type.
+      (setq start-point url-http-end-of-headers)
+      (setq ok (eq (url-http-parse-response) 200)))
+    (let ((new-buffer (get-buffer-create "*Package Info*")))
+      (with-current-buffer new-buffer
+        (let ((buffer-read-only nil))
+          (erase-buffer)
+          (insert "Package information for " pkg-name "\n\n")
+          (if ok
+              (insert-buffer-substring buffer start-point)
+            (insert "This package does not have a README file or commentary comment.\n"))
+          (goto-char (point-min))
+          (view-mode)))
+      (display-buffer new-buffer t))))
+
+(defun package-menu-get-package ()
+  "Return the name of the package on the current line."
+  (save-excursion
+    (beginning-of-line)
+    (if (looking-at ". \\([^ \t]*\\)")
+        (match-string-no-properties 1))))
+
+(defun package-menu-get-version ()
+  "Return the version of the package on the current line."
+  (save-excursion
+    (beginning-of-line)
+    (if (looking-at ". [^ \t]*[ \t]*\\([0-9.]*\\)")
+        (match-string 1))))
+
+(defun package-menu-get-status ()
+  "Get the status of the current line."
+  (save-excursion
+    (if (looking-at ". [^ \t]*[ \t]*[^ \t]*[ \t]*\\([^ \t]*\\)")
+        (match-string 1)
+      "")))
+
+(defun package-menu-execute ()
+  "Perform all the marked actions.
+Packages marked for installation will be downloaded and
+installed.  Packages marked for deletion will be removed.
+Note that after installing packages you will want to restart
+Emacs."
+  (interactive)
+  (goto-char (point-min))
+  (forward-line 2)
+  (while (not (eobp))
+    (let ((cmd (char-after))
+          (pkg-name (package-menu-get-package))
+          (pkg-vers (package-menu-get-version))
+          (pkg-status (package-menu-get-status)))
+      (cond
+       ((eq cmd ?D)
+        (when (and (string= pkg-status "installed")
+                   (string= pkg-name "package"))
+          ;; FIXME: actually, we could be tricky and remove all info.
+          ;; But that is drastic and the user can do that instead.
+          (error "Can't delete most recent version of `package'"))
+        ;; Ask for confirmation here?  Maybe if package status is ""?
+        ;; Or if any lisp from package is actually loaded?
+        (message "Deleting %s-%s..." pkg-name pkg-vers)
+        (package-delete pkg-name pkg-vers)
+        (message "Deleting %s-%s... done" pkg-name pkg-vers))
+       ((eq cmd ?I)
+        (package-install (intern pkg-name)))))
+    (forward-line))
+  (package-menu-revert))
+
+(defun package-print-package (package version key desc)
+  "Print out a single PACKAGE line for the menu buffer.
+
+PACKAGE is the package name as a symbol.
+
+VERSION is the version as an integer vector.
+
+KEY is the installation status of the package; either
+\"available\" or \"installed\".
+
+DESC is the short description of the package."
+  (let ((face
+         (cond ((eq package 'emacs) 'font-lock-builtin-face)
+               ((string= key "available") 'default)
+               ((string= key "installed") 'font-lock-comment-face)
+               (t ; obsolete, but also the default.
+                                        ; is warning ok?
+                'font-lock-warning-face))))
+    (insert (propertize "  " 'font-lock-face face))
+    (insert (propertize (symbol-name package) 'font-lock-face face))
+    (indent-to 20 1)
+    (insert (propertize (package-version-join version) 'font-lock-face face))
+    (indent-to 30 1)
+    (insert (propertize key 'font-lock-face face))
+    ;; FIXME: this 'when' is bogus...
+    (when desc
+      (indent-to 41 1)
+      (insert (propertize desc 'font-lock-face face)))
+    (insert "\n")))
+
+(defun package-list-maybe-add (package version status description result)
+  "Add PACKAGE to the list if it is not already there.
+
+PACKAGE is the package name as a symbol.
+
+VERSION is the package version, as an integer vector.
+
+STATUS is the installation status of the package, either
+\"available\" or \"installed\".
+
+DESCRIPTION is the short description of the package.
+
+RESULT is the list to which to add the package."
+  (let ((elt (assoc (cons package version) result)))
+    (unless elt
+      (setq result (cons (list (cons package version) status description)
+                         result))))
+  result)
+
+;; This decides how we should sort; nil means by package name.
+(defvar package-menu-sort-key nil)
+
+(defun package-list-packages-internal ()
+  "List the available and installed packages."
+  (package-initialize)          ; FIXME: do this here?
+  (with-current-buffer (get-buffer-create "*Packages*")
+    (setq buffer-read-only nil)
+    (erase-buffer)
+    (let ((info-list))
+      (mapc (lambda (elt)
+              (setq info-list
+                    (package-list-maybe-add (car elt)
+                                            (package-desc-vers (cdr elt))
+                                            ;; FIXME: it turns out to
+                                            ;; be tricky to see if
+                                            ;; this package is
+                                            ;; presently activated.
+                                            ;; That is lame!
+                                            "installed"
+                                            (package-desc-doc (cdr elt))
+                                            info-list)))
+            package-alist)
+      (mapc (lambda (elt)
+              (setq info-list
+                    (package-list-maybe-add (car elt)
+                                            (package-desc-vers (cdr elt))
+                                            "available"
+                                            (package-desc-doc (cdr elt))
+                                            info-list)))
+            package-archive-contents)
+      (mapc (lambda (elt)
+              (mapc (lambda (inner-elt)
+                      (setq info-list
+                            (package-list-maybe-add (car elt)
+                                                    (package-desc-vers
+                                                     (cdr inner-elt))
+                                                    "obsolete"
+                                                    (package-desc-doc
+                                                     (cdr inner-elt))
+                                                    info-list)))
+                    (cdr elt)))
+            package-obsolete-alist)
+      (let ((selector (cond
+                       ((string= package-menu-sort-key "Version")
+                        ;; FIXME this doesn't work.
+                        #'(lambda (e) (cdr (car e))))
+                       ((string= package-menu-sort-key "Status")
+                        #'(lambda (e) (car (cdr e))))
+                       ((string= package-menu-sort-key "Description")
+                        #'(lambda (e) (car (cdr (cdr e)))))
+                       (t ; "Package" is default.
+                        #'(lambda (e) (symbol-name (car (car e))))))))
+        (setq info-list
+              (sort info-list
+                    (lambda (left right)
+                      (let ((vleft (funcall selector left))
+                            (vright (funcall selector right)))
+                        (string< vleft vright))))))
+      (mapc (lambda (elt)
+              (package-print-package (car (car elt))
+                                     (cdr (car elt))
+                                     (car (cdr elt))
+                                     (car (cdr (cdr elt)))))
+            info-list))
+    (goto-char (point-min))
+    (current-buffer)))
+
+(defun package-menu-sort-by-column (&optional e)
+  "Sort the package menu by the last column clicked, E."
+  (interactive (list last-input-event))
+  (if e (mouse-select-window e))
+  (let* ((pos (event-start e))
+         (obj (posn-object pos))
+         (col (if obj
+                  (get-text-property (cdr obj) 'column-name (car obj))
+                (get-text-property (posn-point pos) 'column-name))))
+    (setq package-menu-sort-key col))
+  (package-list-packages-internal))
+
+(defun package--list-packages ()
+  "Display a list of packages.
+Helper function that does all the work for the user-facing functions."
+  (with-current-buffer (package-list-packages-internal)
+    (package-menu-mode)
+    ;; Set up the header line.
+    (setq header-line-format
+          (mapconcat
+           (lambda (pair)
+             (let ((column (car pair))
+                   (name (cdr pair)))
+               (concat
+                ;; Insert a space that aligns the button properly.
+                (propertize " " 'display (list 'space :align-to column)
+                            'face 'fixed-pitch)
+                ;; Set up the column button.
+                (if (string= name "Version")
+                    name
+                  (propertize name
+                              'column-name name
+                              'help-echo "mouse-1: sort by column"
+                              'mouse-face 'highlight
+                              'keymap package-menu-sort-button-map)))))
+           ;; We take a trick from buff-menu and have a dummy leading
+           ;; space to align the header line with the beginning of the
+           ;; text.  This doesn't really work properly on Emacs 21,
+           ;; but it is close enough.
+           '((0 . "")
+             (2 . "Package")
+             (20 . "Version")
+             (30 . "Status")
+             (41 . "Description"))
+           ""))
+
+    ;; It's okay to use pop-to-buffer here.  The package menu buffer
+    ;; has keybindings, and the user just typed 'M-x
+    ;; package-list-packages', suggesting that they might want to use
+    ;; them.
+    (pop-to-buffer (current-buffer))))
+
+(defun package-list-packages ()
+  "Display a list of packages.
+Fetches the updated list of packages before displaying.
+The list is displayed in a buffer named `*Packages*'."
+  (interactive)
+  (package-refresh-contents)
+  (package--list-packages))
+
+(defun package-list-packages-no-fetch ()
+  "Display a list of packages.
+Does not fetch the updated list of packages before displaying.
+The list is displayed in a buffer named `*Packages*'."
+  (interactive)
+  (package--list-packages))
+
+;; Make it appear on the menu.
+(define-key-after menu-bar-options-menu [package]
+  '(menu-item "Manage Packages" package-list-packages
+              :help "Install or uninstall additional Emacs packages"))
+
+(provide 'package)
+
+;;; package.el ends here
deleted file mode 100644
--- a/.elisp/paredit.el
+++ /dev/null
@@ -1,1828 +0,0 @@
-;;; -*- Mode: Emacs-Lisp; outline-regexp: "\n;;;;+" -*-
-
-;;;;;; Paredit: Parenthesis-Editing Minor Mode
-;;;;;; Version 20
-
-;;; This code is written by Taylor R. Campbell (except where explicitly
-;;; noted) and placed in the Public Domain.  All warranties are
-;;; disclaimed.
-
-;;; Add this to your .emacs after adding paredit.el to /path/to/elisp/:
-;;;
-;;;   (add-to-list 'load-path "/path/to/elisp/")
-;;;   (autoload 'paredit-mode "paredit"
-;;;     "Minor mode for pseudo-structurally editing Lisp code."
-;;;     t)
-;;;   (add-hook '...-mode-hook (lambda () (paredit-mode +1)))
-;;;
-;;; Usually the ... will be lisp or scheme or both.  Alternatively, you
-;;; can manually toggle this mode with M-x paredit-mode.  Customization
-;;; of paredit can be accomplished with `eval-after-load':
-;;;
-;;;   (eval-after-load 'paredit
-;;;     '(progn ...redefine keys, &c....))
-;;;
-;;; This should run in GNU Emacs 21 or later and XEmacs 21.5 or later.
-;;; It is highly unlikely to work in earlier versions of GNU Emacs, and
-;;; it may have obscure problems in earlier versions of XEmacs due to
-;;; the way its syntax parser reports conditions, as a result of which
-;;; the code that uses the syntax parser must mask *all* error
-;;; conditions, not just those generated by the syntax parser.
-
-;;; This mode changes the keybindings for a number of simple keys,
-;;; notably (, ), ", \, and ;.  The bracket keys (round or square) are
-;;; defined to insert parenthesis pairs and move past the close,
-;;; respectively; the double-quote key is multiplexed to do both, and
-;;; also insert an escape if within a string; backslashes prompt the
-;;; user for the next character to input, because a lone backslash can
-;;; break structure inadvertently; and semicolons ensure that they do
-;;; not accidentally comment valid structure.  (Use M-; to comment an
-;;; expression.)  These all have their ordinary behaviour when inside
-;;; comments, and, outside comments, if truly necessary, you can insert
-;;; them literally with C-q.
-;;;
-;;; These keybindings are set up for my preference.  One particular
-;;; preference which I've seen vary greatly from person to person is
-;;; whether the command to move past a closing delimiter ought to
-;;; insert a newline.  Since I find this behaviour to be more common
-;;; than that which inserts no newline, I have ) bound to it, and the
-;;; more involved M-) to perform the less common action.  This bothers
-;;; some users, though, and they prefer the other way around.  This
-;;; code, which you can use `eval-after-load' to put in your .emacs,
-;;; will exchange the bindings:
-;;;
-;;;   (define-key paredit-mode-map (kbd ")")
-;;;     'paredit-close-parenthesis)
-;;;   (define-key paredit-mode-map (kbd "M-)")
-;;;     'paredit-close-parenthesis-and-newline)
-;;;
-;;; Paredit also changes the bindings of keys for deleting and killing,
-;;; so that they will not destroy any S-expression structure by killing
-;;; or deleting only one side of a bracket or quote pair.  If the point
-;;; is on a closing bracket, DEL will move left over it; if it is on an
-;;; opening bracket, C-d will move right over it.  Only if the point is
-;;; between a pair of brackets will C-d or DEL delete them, and in that
-;;; case it will delete both simultaneously.  M-d and M-DEL kill words,
-;;; but skip over any S-expression structure.  C-k kills from the start
-;;; of the line, either to the line's end, if it contains only balanced
-;;; expressions; to the first closing bracket, if the point is within a
-;;; form that ends on the line; or up to the end of the last expression
-;;; that starts on the line after the point.
-;;;
-;;; Automatic reindentation is performed as locally as possible, to
-;;; ensure that Emacs does not interfere with custom indentation used
-;;; elsewhere in some S-expression.  It is performed only by the
-;;; advanced S-expression frobnication commands, and only on the forms
-;;; that were immediately operated upon (& their subforms).
-;;;
-;;; This code is written for clarity, not efficiency.  S-expressions
-;;; are frequently walked over redundantly.  If you have problems with
-;;; some of the commands taking too long to execute, tell me, but first
-;;; make sure that what you're doing is reasonable: it is stylistically
-;;; bad to have huge, long, hideously nested code anyway.
-;;;
-;;; Questions, bug reports, comments, feature suggestions, &c., can be
-;;; addressed to the author via mail on the host mumble.net to campbell
-;;; or via IRC on irc.freenode.net in the #paredit channel under the
-;;; nickname Riastradh.
-
-;;; This assumes Unix-style LF line endings.
-
-(defconst paredit-version 20)
-
-(eval-and-compile
-
-  (defun paredit-xemacs-p ()
-    ;; No idea I got this definition from.  Edward O'Connor (hober on
-    ;; IRC) suggested the current definition.
-    ;;   (and (boundp 'running-xemacs)
-    ;;        running-xemacs)
-    (featurep 'xemacs))
-
-  (defun paredit-gnu-emacs-p ()
-    (not (paredit-xemacs-p)))
-
-  (defmacro xcond (&rest clauses)
-    "Exhaustive COND.
-Signal an error if no clause matches."
-    `(cond ,@clauses
-           (t (error "XCOND lost."))))
-
-  (defalias 'paredit-warn (if (fboundp 'warn) 'warn 'message))
-
-  (defvar paredit-sexp-error-type
-    (with-temp-buffer
-      (insert "(")
-      (condition-case condition
-          (backward-sexp)
-        (error (if (eq (car condition) 'error)
-                   (paredit-warn "%s%s%s%s"
-                                 "Paredit is unable to discriminate"
-                                 " S-expression parse errors from"
-                                 " other errors. "
-                                 " This may cause obscure problems. "
-                                 " Please upgrade Emacs."))
-               (car condition)))))
-
-  (defmacro paredit-handle-sexp-errors (body &rest handler)
-    `(condition-case ()
-         ,body
-       (,paredit-sexp-error-type ,@handler)))
-
-  (put 'paredit-handle-sexp-errors 'lisp-indent-function 1)
-
-  (defmacro paredit-ignore-sexp-errors (&rest body)
-    `(paredit-handle-sexp-errors (progn ,@body)
-       nil))
-
-  (put 'paredit-ignore-sexp-errors 'lisp-indent-function 0)
-
-  nil)
-
-;;;; Minor Mode Definition
-
-(defvar paredit-mode-map (make-sparse-keymap)
-  "Keymap for the paredit minor mode.")
-
-(define-minor-mode paredit-mode
-  "Minor mode for pseudo-structurally editing Lisp code.
-\\<paredit-mode-map>"
-  :lighter " Paredit"
-  ;; If we're enabling paredit-mode, the prefix to this code that
-  ;; DEFINE-MINOR-MODE inserts will have already set PAREDIT-MODE to
-  ;; true.  If this is the case, then first check the parentheses, and
-  ;; if there are any imbalanced ones we must inhibit the activation of
-  ;; paredit mode.  We skip the check, though, if the user supplied a
-  ;; prefix argument interactively.
-  (if (and paredit-mode
-           (not current-prefix-arg))
-      (if (not (fboundp 'check-parens))
-          (paredit-warn "`check-parens' is not defined; %s"
-                        "be careful of malformed S-expressions.")
-          (condition-case condition
-              (check-parens)
-            (error (setq paredit-mode nil)
-                   (signal (car condition) (cdr condition)))))))
-
-;;; Old functions from when there was a different mode for emacs -nw.
-
-(defun enable-paredit-mode ()
-  "Turn on pseudo-structural editing of Lisp code.
-
-Deprecated: use `paredit-mode' instead."
-  (interactive)
-  (paredit-mode +1))
-
-(defun disable-paredit-mode ()
-  "Turn off pseudo-structural editing of Lisp code.
-
-Deprecated: use `paredit-mode' instead."
-  (interactive)
-  (paredit-mode -1))
-
-(defvar paredit-backward-delete-key
-  (xcond ((paredit-xemacs-p)    "BS")
-         ((paredit-gnu-emacs-p) "DEL")))
-
-(defvar paredit-forward-delete-keys
-  (xcond ((paredit-xemacs-p)    '("DEL"))
-         ((paredit-gnu-emacs-p) '("<delete>" "<deletechar>"))))
-
-;;;; Paredit Keys
-
-;;; Separating the definition and initialization of this variable
-;;; simplifies the development of paredit, since re-evaluating DEFVAR
-;;; forms doesn't actually do anything.
-
-(defvar paredit-commands nil
-  "List of paredit commands with their keys and examples.")
-
-;;; Each specifier is of the form:
-;;;   (key[s] function (example-input example-output) ...)
-;;; where key[s] is either a single string suitable for passing to KBD
-;;; or a list of such strings.  Entries in this list may also just be
-;;; strings, in which case they are headings for the next entries.
-
-(progn (setq paredit-commands
- `(
-   "Basic Insertion Commands"
-   ("("         paredit-open-parenthesis
-                ("(a b |c d)"
-                 "(a b (|) c d)")
-                ("(foo \"bar |baz\" quux)"
-                 "(foo \"bar (|baz\" quux)"))
-   (")"         paredit-close-parenthesis-and-newline
-                ("(defun f (x|  ))"
-                 "(defun f (x)\n  |)")
-                ("; (Foo.|"
-                 "; (Foo.)|"))
-   ("M-)"       paredit-close-parenthesis
-                ("(a b |c   )" "(a b c)|")
-                ("; Hello,| world!"
-                 "; Hello,)| world!"))
-   ("["         paredit-open-bracket
-                ("(a b |c d)"
-                 "(a b [|] c d)")
-                ("(foo \"bar |baz\" quux)"
-                 "(foo \"bar [baz\" quux)"))
-   ("]"         paredit-close-bracket
-                ("(define-key keymap [frob|  ] 'frobnicate)"
-                 "(define-key keymap [frob]| 'frobnicate)")
-                ("; [Bar.|"
-                 "; [Bar.]|"))
-   ("\""        paredit-doublequote
-                ("(frob grovel |full lexical)"
-                 "(frob grovel \"|\" full lexical)")
-                ("(foo \"bar |baz\" quux)"
-                 "(foo \"bar \\\"|baz\" quux)"))
-   ("M-\""      paredit-meta-doublequote
-                ("(foo \"bar |baz\" quux)"
-                 "(foo \"bar baz\"\n     |quux)")
-                ("(foo |(bar #\\x \"baz \\\\ quux\") zot)"
-                 ,(concat "(foo \"|(bar #\\\\x \\\"baz \\\\"
-                          "\\\\ quux\\\")\" zot)")))
-   ("\\"        paredit-backslash
-                ("(string #|)\n  ; Escaping character... (x)"
-                 "(string #\\x|)")
-                ("\"foo|bar\"\n  ; Escaping character... (\")"
-                 "\"foo\\\"|bar\""))
-   (";"         paredit-semicolon
-                ("|(frob grovel)"
-                 ";|\n(frob grovel)")
-                ("(frob grovel)    |"
-                 "(frob grovel)    ;|"))
-   ("M-;"       paredit-comment-dwim
-                ("(foo |bar)   ; baz"
-                 "(foo bar)                               ; |baz")
-                ("(frob grovel)|"
-                 "(frob grovel)                           ;|")
-                ("    (foo bar)\n|\n    (baz quux)"
-                 "    (foo bar)\n    ;; |\n    (baz quux)")
-                ("    (foo bar) |(baz quux)"
-                 "    (foo bar)\n    ;; |\n    (baz quux)")
-                ("|(defun hello-world ...)"
-                 ";;; |\n(defun hello-world ...)"))
-
-   ("C-j"       paredit-newline
-                ("(let ((n (frobbotz))) |(display (+ n 1)\nport))"
-                 ,(concat "(let ((n (frobbotz)))"
-                          "\n  |(display (+ n 1)"
-                          "\n            port))")))
-
-   "Deleting & Killing"
-   (("C-d" ,@paredit-forward-delete-keys)
-                paredit-forward-delete
-                ("(quu|x \"zot\")" "(quu| \"zot\")")
-                ("(quux |\"zot\")"
-                 "(quux \"|zot\")"
-                 "(quux \"|ot\")")
-                ("(foo (|) bar)" "(foo | bar)")
-                ("|(foo bar)" "(|foo bar)"))
-   (,paredit-backward-delete-key
-                paredit-backward-delete
-                ("(\"zot\" q|uux)" "(\"zot\" |uux)")
-                ("(\"zot\"| quux)"
-                 "(\"zot|\" quux)"
-                 "(\"zo|\" quux)")
-                ("(foo (|) bar)" "(foo | bar)")
-                ("(foo bar)|" "(foo bar|)"))
-   ("C-k"       paredit-kill
-                ("(foo bar)|     ; Useless comment!"
-                 "(foo bar)|")
-                ("(|foo bar)     ; Useful comment!"
-                 "(|)     ; Useful comment!")
-                ("|(foo bar)     ; Useless line!"
-                 "|")
-                ("(foo \"|bar baz\"\n     quux)"
-                 "(foo \"|\"\n     quux)"))
-   ("M-d"       paredit-forward-kill-word
-                ("|(foo bar)    ; baz"
-                 "(| bar)    ; baz"
-                 "(|)    ; baz"
-                 "()    ;|")
-                (";;;| Frobnicate\n(defun frobnicate ...)"
-                 ";;;|\n(defun frobnicate ...)"
-                 ";;;\n(| frobnicate ...)"))
-   (,(concat "M-" paredit-backward-delete-key)
-                paredit-backward-kill-word
-                ("(foo bar)    ; baz\n(quux)|"
-                 "(foo bar)    ; baz\n(|)"
-                 "(foo bar)    ; |\n()"
-                 "(foo |)    ; \n()"
-                 "(|)    ; \n()"))
-
-   "Movement & Navigation"
-   ("C-M-f"     paredit-forward
-                ("(foo |(bar baz) quux)"
-                 "(foo (bar baz)| quux)")
-                ("(foo (bar)|)"
-                 "(foo (bar))|"))
-   ("C-M-b"     paredit-backward
-                ("(foo (bar baz)| quux)"
-                 "(foo |(bar baz) quux)")
-                ("(|(foo) bar)"
-                 "|((foo) bar)"))
-;;;("C-M-u"     backward-up-list)       ; These two are built-in.
-;;;("C-M-d"     down-list)
-   ("C-M-p"     backward-down-list)     ; Built-in, these are FORWARD-
-   ("C-M-n"     up-list)                ; & BACKWARD-LIST, which have
-                                        ; no need given C-M-f & C-M-b.
-
-   "Depth-Changing Commands"
-   ("M-("       paredit-wrap-sexp
-                ("(foo |bar baz)"
-                 "(foo (|bar) baz)"))
-   ("M-["       paredit-bracket-wrap-sexp
-                ("(foo |bar baz)"
-                 "(foo [|bar] baz)"))
-   ("M-s"       paredit-splice-sexp
-                ("(foo (bar| baz) quux)"
-                 "(foo bar| baz quux)"))
-   (("M-<up>" "ESC <up>")
-                paredit-splice-sexp-killing-backward
-                ("(foo (let ((x 5)) |(sqrt n)) bar)"
-                 "(foo (sqrt n) bar)"))
-   (("M-<down>" "ESC <down>")
-                paredit-splice-sexp-killing-forward
-                ("(a (b c| d e) f)"
-                 "(a b c f)"))
-   ("M-r"       paredit-raise-sexp
-                ("(dynamic-wind in (lambda () |body) out)"
-                 "(dynamic-wind in |body out)"
-                 "|body"))
-
-   "Barfage & Slurpage"
-   (("C-)" "C-<right>")
-                paredit-forward-slurp-sexp
-                ("(foo (bar |baz) quux zot)"
-                 "(foo (bar |baz quux) zot)")
-                ("(a b ((c| d)) e f)"
-                 "(a b ((c| d) e) f)"))
-   (("C-}" "C-<left>")
-                paredit-forward-barf-sexp
-                ("(foo (bar |baz quux) zot)"
-                 "(foo (bar |baz) quux zot)"))
-   (("C-(" "C-M-<left>" "ESC C-<left>")
-                paredit-backward-slurp-sexp
-                ("(foo bar (baz| quux) zot)"
-                 "(foo (bar baz| quux) zot)")
-                ("(a b ((c| d)) e f)"
-                 "(a (b (c| d)) e f)"))
-   (("C-{" "C-M-<right>" "ESC C-<right>")
-                paredit-backward-barf-sexp
-                ("(foo (bar baz |quux) zot)"
-                 "(foo bar (baz |quux) zot)"))
-
-   "Miscellaneous Commands"
-   ("M-S"       paredit-split-sexp
-                ("(hello| world)"
-                 "(hello)| (world)")
-                ("\"Hello, |world!\""
-                 "\"Hello, \"| \"world!\""))
-   ("M-J"       paredit-join-sexps
-                ("(hello)| (world)"
-                 "(hello| world)")
-                ("\"Hello, \"| \"world!\""
-                 "\"Hello, |world!\"")
-                ("hello-\n|  world"
-                 "hello-|world"))
-   ("C-c C-M-l" paredit-recentre-on-sexp)
-   ))
-       nil)                             ; end of PROGN
-
-;;;;; Command Examples
-
-(eval-and-compile
-  (defmacro paredit-do-commands (vars string-case &rest body)
-    (let ((spec     (nth 0 vars))
-          (keys     (nth 1 vars))
-          (fn       (nth 2 vars))
-          (examples (nth 3 vars)))
-      `(dolist (,spec paredit-commands)
-         (if (stringp ,spec)
-             ,string-case
-           (let ((,keys (let ((k (car ,spec)))
-                          (cond ((stringp k) (list k))
-                                ((listp k) k)
-                                (t (error "Invalid paredit command %s."
-                                          ,spec)))))
-                 (,fn (cadr ,spec))
-                 (,examples (cddr ,spec)))
-             ,@body)))))
-
-  (put 'paredit-do-commands 'lisp-indent-function 2))
-
-(defun paredit-define-keys ()
-  (paredit-do-commands (spec keys fn examples)
-      nil       ; string case
-    (dolist (key keys)
-      (define-key paredit-mode-map (read-kbd-macro key) fn))))
-
-(defun paredit-function-documentation (fn)
-  (let ((original-doc (get fn 'paredit-original-documentation))
-        (doc (documentation fn 'function-documentation)))
-    (or original-doc
-        (progn (put fn 'paredit-original-documentation doc)
-               doc))))
-
-(defun paredit-annotate-mode-with-examples ()
-  (let ((contents
-         (list (paredit-function-documentation 'paredit-mode))))
-    (paredit-do-commands (spec keys fn examples)
-        (push (concat "\n\n" spec "\n")
-              contents)
-      (let ((name (symbol-name fn)))
-        (if (string-match (symbol-name 'paredit-) name)
-            (push (concat "\n\n\\[" name "]\t" name
-                          (if examples
-                              (mapconcat (lambda (example)
-                                           (concat
-                                            "\n"
-                                            (mapconcat 'identity
-                                                       example
-                                                       "\n  --->\n")
-                                            "\n"))
-                                         examples
-                                         "")
-                              "\n  (no examples)\n"))
-                  contents))))
-    (put 'paredit-mode 'function-documentation
-         (apply 'concat (reverse contents))))
-  ;; PUT returns the huge string we just constructed, which we don't
-  ;; want it to return.
-  nil)
-
-(defun paredit-annotate-functions-with-examples ()
-  (paredit-do-commands (spec keys fn examples)
-      nil       ; string case
-    (put fn 'function-documentation
-         (concat (paredit-function-documentation fn)
-                 "\n\n\\<paredit-mode-map>\\[" (symbol-name fn) "]\n"
-                 (mapconcat (lambda (example)
-                              (concat "\n"
-                                      (mapconcat 'identity
-                                                 example
-                                                 "\n  ->\n")
-                                      "\n"))
-                            examples
-                            "")))))
-
-;;;;; HTML Examples
-
-(defun paredit-insert-html-examples ()
-  "Insert HTML for a paredit quick reference table."
-  (interactive)
-  (let ((insert-lines (lambda (&rest lines)
-                        (mapc (lambda (line) (insert line) (newline))
-                              lines)))
-        (html-keys (lambda (keys)
-                     (mapconcat 'paredit-html-quote keys ", ")))
-        (html-example
-         (lambda (example)
-           (concat "<table><tr><td><pre>"
-                   (mapconcat 'paredit-html-quote
-                              example
-                              (concat "</pre></td></tr><tr><td>"
-                                      "&nbsp;&nbsp;&nbsp;&nbsp;---&gt;"
-                                      "</td></tr><tr><td><pre>"))
-                   "</pre></td></tr></table>")))
-        (firstp t))
-    (paredit-do-commands (spec keys fn examples)
-        (progn (if (not firstp)
-                   (insert "</table>\n")
-                   (setq firstp nil))
-               (funcall insert-lines
-                        (concat "<h3>" spec "</h3>")
-                        "<table border=\"1\" cellpadding=\"1\">"
-                        "  <tr>"
-                        "    <th>Command</th>"
-                        "    <th>Keys</th>"
-                        "    <th>Examples</th>"
-                        "  </tr>"))
-      (let ((name (symbol-name fn)))
-        (if (string-match (symbol-name 'paredit-) name)
-            (funcall insert-lines
-                     "  <tr>"
-                     (concat "    <td><tt>" name "</tt></td>")
-                     (concat "    <td align=\"center\">"
-                             (funcall html-keys keys)
-                             "</td>")
-                     (concat "    <td>"
-                             (if examples
-                                 (mapconcat html-example examples
-                                            "<hr>")
-                                 "(no examples)")
-                             "</td>")
-                     "  </tr>")))))
-  (insert "</table>\n"))
-
-(defun paredit-html-quote (string)
-  (with-temp-buffer
-    (dotimes (i (length string))
-      (insert (let ((c (elt string i)))
-                (cond ((eq c ?\<) "&lt;")
-                      ((eq c ?\>) "&gt;")
-                      ((eq c ?\&) "&amp;")
-                      ((eq c ?\') "&apos;")
-                      ((eq c ?\") "&quot;")
-                      (t c)))))
-    (buffer-string)))
-
-;;;; Delimiter Insertion
-
-(eval-and-compile
-  (defun paredit-conc-name (&rest strings)
-    (intern (apply 'concat strings)))
-
-  (defmacro define-paredit-pair (open close name)
-    `(progn
-       (defun ,(paredit-conc-name "paredit-open-" name) (&optional n)
-         ,(concat "Insert a balanced " name " pair.
-With a prefix argument N, put the closing " name " after N
-  S-expressions forward.
-If the region is active, `transient-mark-mode' is enabled, and the
-  region's start and end fall in the same parenthesis depth, insert a
-  " name " pair around the region.
-If in a string or a comment, insert a single " name ".
-If in a character literal, do nothing.  This prevents changing what was
-  in the character literal to a meaningful delimiter unintentionally.")
-         (interactive "P")
-         (cond ((or (paredit-in-string-p)
-                    (paredit-in-comment-p))
-                (insert ,open))
-               ((not (paredit-in-char-p))
-                (paredit-insert-pair n ,open ,close 'goto-char))))
-       (defun ,(paredit-conc-name "paredit-close-" name) ()
-         ,(concat "Move past one closing delimiter and reindent.
-\(Agnostic to the specific closing delimiter.)
-If in a string or comment, insert a single closing " name ".
-If in a character literal, do nothing.  This prevents changing what was
-  in the character literal to a meaningful delimiter unintentionally.")
-         (interactive)
-         (paredit-move-past-close ,close))
-       (defun ,(paredit-conc-name "paredit-close-" name "-and-newline") ()
-         ,(concat "Move past one closing delimiter, add a newline,"
-                  " and reindent.
-If there was a margin comment after the closing delimiter, preserve it
-  on the same line.")
-         (interactive)
-         (paredit-move-past-close-and-newline ,close))
-       (defun ,(paredit-conc-name "paredit-" name "-wrap-sexp") (&optional n)
-         ,(concat "Wrap a pair of " name " around a sexp")
-         (interactive "P")
-         (paredit-wrap-sexp n ,open ,close)))))
-
-(define-paredit-pair ?\( ?\) "parenthesis")
-(define-paredit-pair ?\[ ?\] "bracket")
-(define-paredit-pair ?\{ ?\} "brace")
-(define-paredit-pair ?\< ?\> "brocket")
-
-(defun paredit-move-past-close (close)
-  (cond ((or (paredit-in-string-p)
-             (paredit-in-comment-p))
-         (insert close))
-        ((not (paredit-in-char-p))
-         (paredit-move-past-close-and-reindent)
-         (paredit-blink-paren-match nil))))
-
-(defun paredit-move-past-close-and-newline (close)
-  (cond ((or (paredit-in-string-p)
-             (paredit-in-comment-p))
-         (insert close))
-        (t (if (paredit-in-char-p) (forward-char))
-           (paredit-move-past-close-and-reindent)
-           (let ((comment.point (paredit-find-comment-on-line)))
-             (newline)
-             (if comment.point
-                 (save-excursion
-                   (forward-line -1)
-                   (end-of-line)
-                   (indent-to (cdr comment.point))
-                   (insert (car comment.point)))))
-           (lisp-indent-line)
-           (paredit-ignore-sexp-errors (indent-sexp))
-           (paredit-blink-paren-match t))))
-
-(defun paredit-find-comment-on-line ()
-  "Find a margin comment on the current line.
-If such a comment exists, delete the comment (including all leading
-  whitespace) and return a cons whose car is the comment as a string
-  and whose cdr is the point of the comment's initial semicolon,
-  relative to the start of the line."
-  (save-excursion
-    (catch 'return
-      (while t
-        (if (search-forward ";" (point-at-eol) t)
-            (if (not (or (paredit-in-string-p)
-                         (paredit-in-char-p)))
-                (let* ((start (progn (backward-char)  ;before semicolon
-                                     (point)))
-                       (comment (buffer-substring start
-                                                  (point-at-eol))))
-                  (paredit-skip-whitespace nil (point-at-bol))
-                  (delete-region (point) (point-at-eol))
-                  (throw 'return
-                         (cons comment (- start (point-at-bol))))))
-            (throw 'return nil))))))
-
-(defun paredit-insert-pair (n open close forward)
-  (let* ((regionp (and (paredit-region-active-p)
-                       (paredit-region-safe-for-insert-p)))
-         (end (and regionp
-                   (not n)
-                   (prog1 (region-end)
-                     (goto-char (region-beginning))))))
-    (let ((spacep (paredit-space-for-delimiter-p nil open)))
-      (if spacep (insert " "))
-      (insert open)
-      (save-excursion
-        ;; Move past the desired region.
-        (cond (n (funcall forward
-                          (save-excursion
-                            (forward-sexp (prefix-numeric-value n))
-                            (point))))
-              (regionp (funcall forward (+ end (if spacep 2 1)))))
-        (insert close)
-        (if (paredit-space-for-delimiter-p t close)
-            (insert " "))))))
-
-(defun paredit-region-safe-for-insert-p ()
-  (save-excursion
-    (let ((beginning (region-beginning))
-          (end (region-end)))
-      (goto-char beginning)
-      (let* ((beginning-state (paredit-current-parse-state))
-             (end-state (parse-partial-sexp beginning end
-                                            nil nil beginning-state)))
-        (and (=  (nth 0 beginning-state)   ; 0. depth in parens
-                 (nth 0 end-state))
-             (eq (nth 3 beginning-state)   ; 3. non-nil if inside a
-                 (nth 3 end-state))        ;    string
-             (eq (nth 4 beginning-state)   ; 4. comment status, yada
-                 (nth 4 end-state))
-             (eq (nth 5 beginning-state)   ; 5. t if following char
-                 (nth 5 end-state)))))))   ;    quote
-
-(defun paredit-space-for-delimiter-p (endp delimiter)
-  ;; If at the buffer limit, don't insert a space.  If there is a word,
-  ;; symbol, other quote, or non-matching parenthesis delimiter (i.e. a
-  ;; close when want an open the string or an open when we want to
-  ;; close the string), do insert a space.
-  (and (not (if endp (eobp) (bobp)))
-       (memq (char-syntax (if endp
-                              (char-after)
-                              (char-before)))
-             (list ?w ?_ ?\"
-                   (let ((matching (matching-paren delimiter)))
-                     (and matching (char-syntax matching)))))))
-
-(defun paredit-move-past-close-and-reindent ()
-  (let ((orig (point)))
-    (up-list)
-    (if (catch 'return                  ; This CATCH returns T if it
-          (while t                      ; should delete leading spaces
-            (save-excursion             ; and NIL if not.
-              (let ((before-paren (1- (point))))
-                (back-to-indentation)
-                (cond ((not (eq (point) before-paren))
-                       ;; Can't call PAREDIT-DELETE-LEADING-WHITESPACE
-                       ;; here -- we must return from SAVE-EXCURSION
-                       ;; first.
-                       (throw 'return t))
-                      ((save-excursion (forward-line -1)
-                                       (end-of-line)
-                                       (paredit-in-comment-p))
-                       ;; Moving the closing parenthesis any further
-                       ;; would put it into a comment, so we just
-                       ;; indent the closing parenthesis where it is
-                       ;; and abort the loop, telling its continuation
-                       ;; that no leading whitespace should be deleted.
-                       (lisp-indent-line)
-                       (throw 'return nil))
-                      (t (delete-indentation)))))))
-        (paredit-delete-leading-whitespace))))
-
-(defun paredit-delete-leading-whitespace ()
-  ;; This assumes that we're on the closing parenthesis already.
-  (save-excursion
-    (backward-char)
-    (while (let ((syn (char-syntax (char-before))))
-             (and (or (eq syn ?\ ) (eq syn ?-))     ; whitespace syntax
-                  ;; The above line is a perfect example of why the
-                  ;; following test is necessary.
-                  (not (paredit-in-char-p (1- (point))))))
-      (backward-delete-char 1))))
-
-(defun paredit-blink-paren-match (another-line-p)
-  (if (and blink-matching-paren
-           (or (not show-paren-mode) another-line-p))
-      (paredit-ignore-sexp-errors
-        (save-excursion
-          (backward-sexp)
-          (forward-sexp)
-          ;; SHOW-PAREN-MODE inhibits any blinking, so we disable it
-          ;; locally here.
-          (let ((show-paren-mode nil))
-            (blink-matching-open))))))
-
-(defun paredit-doublequote (&optional n)
-  "Insert a pair of double-quotes.
-With a prefix argument N, wrap the following N S-expressions in
-  double-quotes, escaping intermediate characters if necessary.
-If the region is active, `transient-mark-mode' is enabled, and the
-  region's start and end fall in the same parenthesis depth, insert a
-  pair of double-quotes around the region, again escaping intermediate
-  characters if necessary.
-Inside a comment, insert a literal double-quote.
-At the end of a string, move past the closing double-quote.
-In the middle of a string, insert a backslash-escaped double-quote.
-If in a character literal, do nothing.  This prevents accidentally
-  changing a what was in the character literal to become a meaningful
-  delimiter unintentionally."
-  (interactive "P")
-  (cond ((paredit-in-string-p)
-         (if (eq (cdr (paredit-string-start+end-points))
-                 (point))
-             (forward-char)             ; We're on the closing quote.
-             (insert ?\\ ?\" )))
-        ((paredit-in-comment-p)
-         (insert ?\" ))
-        ((not (paredit-in-char-p))
-         (paredit-insert-pair n ?\" ?\" 'paredit-forward-for-quote))))
-
-(defun paredit-meta-doublequote (&optional n)
-  "Move to the end of the string, insert a newline, and indent.
-If not in a string, act as `paredit-doublequote'; if no prefix argument
-  is specified and the region is not active or `transient-mark-mode' is
-  disabled, the default is to wrap one S-expression, however, not
-  zero."
-  (interactive "P")
-  (if (not (paredit-in-string-p))
-      (paredit-doublequote (or n
-                               (and (not (paredit-region-active-p))
-                                    1)))
-    (let ((start+end (paredit-string-start+end-points)))
-      (goto-char (1+ (cdr start+end)))
-      (newline)
-      (lisp-indent-line)
-      (paredit-ignore-sexp-errors (indent-sexp)))))
-
-(defun paredit-forward-for-quote (end)
-  (let ((state (paredit-current-parse-state)))
-    (while (< (point) end)
-      (let ((new-state (parse-partial-sexp (point) (1+ (point))
-                                           nil nil state)))
-        (if (paredit-in-string-p new-state)
-            (if (not (paredit-in-string-escape-p))
-                (setq state new-state)
-              ;; Escape character: turn it into an escaped escape
-              ;; character by appending another backslash.
-              (insert ?\\ )
-              ;; Now the point is after both escapes, and we want to
-              ;; rescan from before the first one to after the second
-              ;; one.
-              (setq state
-                    (parse-partial-sexp (- (point) 2) (point)
-                                        nil nil state))
-              ;; Advance the end point, since we just inserted a new
-              ;; character.
-              (setq end (1+ end)))
-          ;; String: escape by inserting a backslash before the quote.
-          (backward-char)
-          (insert ?\\ )
-          ;; The point is now between the escape and the quote, and we
-          ;; want to rescan from before the escape to after the quote.
-          (setq state
-                (parse-partial-sexp (1- (point)) (1+ (point))
-                                    nil nil state))
-          ;; Advance the end point for the same reason as above.
-          (setq end (1+ end)))))))
-
-;;;; Escape Insertion
-
-(defun paredit-backslash ()
-  "Insert a backslash followed by a character to escape."
-  (interactive)
-  (insert ?\\ )
-  ;; This funny conditional is necessary because PAREDIT-IN-COMMENT-P
-  ;; assumes that PAREDIT-IN-STRING-P already returned false; otherwise
-  ;; it may give erroneous answers.
-  (if (or (paredit-in-string-p)
-          (not (paredit-in-comment-p)))
-      (let ((delp t))
-        (unwind-protect (setq delp
-                              (call-interactively 'paredit-escape))
-          ;; We need this in an UNWIND-PROTECT so that the backlash is
-          ;; left in there *only* if PAREDIT-ESCAPE return NIL normally
-          ;; -- in any other case, such as the user hitting C-g or an
-          ;; error occurring, we must delete the backslash to avoid
-          ;; leaving a dangling escape.  (This control structure is a
-          ;; crock.)
-          (if delp (backward-delete-char 1))))))
-
-;;; This auxiliary interactive function returns true if the backslash
-;;; should be deleted and false if not.
-
-(defun paredit-escape (char)
-  ;; I'm too lazy to figure out how to do this without a separate
-  ;; interactive function.
-  (interactive "cEscaping character...")
-  (if (eq char 127)                     ; The backslash was a typo, so
-      t                                 ; the luser wants to delete it.
-    (insert char)                       ; (Is there a better way to
-    nil))                               ; express the rubout char?
-                                        ; ?\^? works, but ugh...)
-
-;;; The placement of this function in this file is totally random.
-
-(defun paredit-newline ()
-  "Insert a newline and indent it.
-This is like `newline-and-indent', but it not only indents the line
-  that the point is on but also the S-expression following the point,
-  if there is one.
-Move forward one character first if on an escaped character.
-If in a string, just insert a literal newline."
-  (interactive)
-  (if (paredit-in-string-p)
-      (newline)
-    (if (and (not (paredit-in-comment-p)) (paredit-in-char-p))
-        (forward-char))
-    (newline-and-indent)
-    ;; Indent the following S-expression, but don't signal an error if
-    ;; there's only a closing parenthesis after the point.
-    (paredit-ignore-sexp-errors (indent-sexp))))
-
-;;;; Comment Insertion
-
-(defun paredit-semicolon (&optional n)
-  "Insert a semicolon, moving any code after the point to a new line.
-If in a string, comment, or character literal, insert just a literal
-  semicolon, and do not move anything to the next line.
-With a prefix argument N, insert N semicolons."
-  (interactive "P")
-  (if (not (or (paredit-in-string-p)
-               (paredit-in-comment-p)
-               (paredit-in-char-p)
-               ;; No more code on the line after the point.
-               (save-excursion
-                 (paredit-skip-whitespace t (point-at-eol))
-                 (or (eolp)
-                     ;; Let the user prefix semicolons to existing
-                     ;; comments.
-                     (eq (char-after) ?\;)))))
-      ;; Don't use NEWLINE-AND-INDENT, because that will delete all of
-      ;; the horizontal whitespace first, but we just want to move the
-      ;; code following the point onto the next line while preserving
-      ;; the point on this line.
-      ;++ Why indent only the line?
-      (save-excursion (newline) (lisp-indent-line)))
-  (insert (make-string (if n (prefix-numeric-value n) 1)
-                       ?\; )))
-
-(defun paredit-comment-dwim (&optional arg)
-  "Call the Lisp comment command you want (Do What I Mean).
-This is like `comment-dwim', but it is specialized for Lisp editing.
-If transient mark mode is enabled and the mark is active, comment or
-  uncomment the selected region, depending on whether it was entirely
-  commented not not already.
-If there is already a comment on the current line, with no prefix
-  argument, indent to that comment; with a prefix argument, kill that
-  comment.
-Otherwise, insert a comment appropriate for the context and ensure that
-  any code following the comment is moved to the next line.
-At the top level, where indentation is calculated to be at column 0,
-  insert a triple-semicolon comment; within code, where the indentation
-  is calculated to be non-zero, and on the line there is either no code
-  at all or code after the point, insert a double-semicolon comment;
-  and if the point is after all code on the line, insert a single-
-  semicolon margin comment at `comment-column'."
-  (interactive "*P")
-  (require 'newcomment)
-  (comment-normalize-vars)
-  (cond ((paredit-region-active-p)
-         (comment-or-uncomment-region (region-beginning)
-                                      (region-end)
-                                      arg))
-        ((paredit-comment-on-line-p)
-         (if arg
-             (comment-kill (if (integerp arg) arg nil))
-             (comment-indent)))
-        (t (paredit-insert-comment))))
-
-(defun paredit-comment-on-line-p ()
-  (save-excursion
-    (beginning-of-line)
-    (let ((comment-p nil))
-      ;; Search forward for a comment beginning.  If there is one, set
-      ;; COMMENT-P to true; if not, it will be nil.
-      (while (progn (setq comment-p
-                          (search-forward ";" (point-at-eol)
-                                          ;; t -> no error
-                                          t))
-                    (and comment-p
-                         (or (paredit-in-string-p)
-                             (paredit-in-char-p (1- (point))))))
-        (forward-char))
-      comment-p)))
-
-(defun paredit-insert-comment ()
-  (let ((code-after-p
-         (save-excursion (paredit-skip-whitespace t (point-at-eol))
-                         (not (eolp))))
-        (code-before-p
-         (save-excursion (paredit-skip-whitespace nil (point-at-bol))
-                         (not (bolp)))))
-    (if (and (bolp)
-             ;; We have to use EQ 0 here and not ZEROP because ZEROP
-             ;; signals an error if its argument is non-numeric, but
-             ;; CALCULATE-LISP-INDENT may return nil.
-             (eq (let ((indent (calculate-lisp-indent)))
-                   (if (consp indent)
-                       (car indent)
-                     indent))
-                 0))
-        ;; Top-level comment
-        (progn (if code-after-p (save-excursion (newline)))
-               (insert ";;; "))
-      (if code-after-p
-          ;; Code comment
-          (progn (if code-before-p
-                     ;++ Why NEWLINE-AND-INDENT here and not just
-                     ;++ NEWLINE, or PAREDIT-NEWLINE?
-                     (newline-and-indent))
-                 (lisp-indent-line)
-                 (insert ";; ")
-                 ;; Move the following code.  (NEWLINE-AND-INDENT will
-                 ;; delete whitespace after the comment, though, so use
-                 ;; NEWLINE & LISP-INDENT-LINE manually here.)
-                 (save-excursion (newline)
-                                 (lisp-indent-line)))
-          ;; Margin comment
-          (progn (indent-to comment-column
-                            1)          ; 1 -> force one leading space
-                 (insert ?\; ))))))
-
-;;;; Character Deletion
-
-(defun paredit-forward-delete (&optional arg)
-  "Delete a character forward or move forward over a delimiter.
-If on an opening S-expression delimiter, move forward into the
-  S-expression.
-If on a closing S-expression delimiter, refuse to delete unless the
-  S-expression is empty, in which case delete the whole S-expression.
-With a prefix argument, simply delete a character forward, without
-  regard for delimiter balancing."
-  (interactive "P")
-  (cond ((or arg (eobp))
-         (delete-char 1))
-        ((paredit-in-string-p)
-         (paredit-forward-delete-in-string))
-        ((paredit-in-comment-p)
-         ;++ What to do here?  This could move a partial S-expression
-         ;++ into a comment and thereby invalidate the file's form,
-         ;++ or move random text out of a comment.
-         (delete-char 1))
-        ((paredit-in-char-p)            ; Escape -- delete both chars.
-         (backward-delete-char 1)
-         (delete-char 1))
-        ((eq (char-after) ?\\ )         ; ditto
-         (delete-char 2))
-        ((let ((syn (char-syntax (char-after))))
-           (or (eq syn ?\( )
-               (eq syn ?\" )))
-         (forward-char))
-        ((and (not (paredit-in-char-p (1- (point))))
-              (eq (char-syntax (char-after)) ?\) )
-              (eq (char-before) (matching-paren (char-after))))
-         (backward-delete-char 1)       ; Empty list -- delete both
-         (delete-char 1))               ;   delimiters.
-        ;; Just delete a single character, if it's not a closing
-        ;; parenthesis.  (The character literal case is already
-        ;; handled by now.)
-        ((not (eq (char-syntax (char-after)) ?\) ))
-         (delete-char 1))))
-
-(defun paredit-forward-delete-in-string ()
-  (let ((start+end (paredit-string-start+end-points)))
-    (cond ((not (eq (point) (cdr start+end)))
-           ;; If it's not the close-quote, it's safe to delete.  But
-           ;; first handle the case that we're in a string escape.
-           (cond ((paredit-in-string-escape-p)
-                  ;; We're right after the backslash, so backward
-                  ;; delete it before deleting the escaped character.
-                  (backward-delete-char 1))
-                 ((eq (char-after) ?\\ )
-                  ;; If we're not in a string escape, but we are on a
-                  ;; backslash, it must start the escape for the next
-                  ;; character, so delete the backslash before deleting
-                  ;; the next character.
-                  (delete-char 1)))
-           (delete-char 1))
-          ((eq (1- (point)) (car start+end))
-           ;; If it is the close-quote, delete only if we're also right
-           ;; past the open-quote (i.e. it's empty), and then delete
-           ;; both quotes.  Otherwise we refuse to delete it.
-           (backward-delete-char 1)
-           (delete-char 1)))))
-
-(defun paredit-backward-delete (&optional arg)
-  "Delete a character backward or move backward over a delimiter.
-If on a closing S-expression delimiter, move backward into the
-  S-expression.
-If on an opening S-expression delimiter, refuse to delete unless the
-  S-expression is empty, in which case delete the whole S-expression.
-With a prefix argument, simply delete a character backward, without
-  regard for delimiter balancing."
-  (interactive "P")
-  (cond ((or arg (bobp))
-         (backward-delete-char 1))      ;++ should this untabify?
-        ((paredit-in-string-p)
-         (paredit-backward-delete-in-string))
-        ((paredit-in-comment-p)
-         (backward-delete-char 1))
-        ((paredit-in-char-p)            ; Escape -- delete both chars.
-         (backward-delete-char 1)
-         (delete-char 1))
-        ((paredit-in-char-p (1- (point)))
-         (backward-delete-char 2))      ; ditto
-        ((let ((syn (char-syntax (char-before))))
-           (or (eq syn ?\) )
-               (eq syn ?\" )))
-         (backward-char))
-        ((and (eq (char-syntax (char-before)) ?\( )
-              (eq (char-after) (matching-paren (char-before))))
-         (backward-delete-char 1)       ; Empty list -- delete both
-         (delete-char 1))               ;   delimiters.
-        ;; Delete it, unless it's an opening parenthesis.  The case
-        ;; of character literals is already handled by now.
-        ((not (eq (char-syntax (char-before)) ?\( ))
-         (backward-delete-char-untabify 1))))
-
-(defun paredit-backward-delete-in-string ()
-  (let ((start+end (paredit-string-start+end-points)))
-    (cond ((not (eq (1- (point)) (car start+end)))
-           ;; If it's not the open-quote, it's safe to delete.
-           (if (paredit-in-string-escape-p)
-               ;; If we're on a string escape, since we're about to
-               ;; delete the backslash, we must first delete the
-               ;; escaped char.
-               (delete-char 1))
-           (backward-delete-char 1)
-           (if (paredit-in-string-escape-p)
-               ;; If, after deleting a character, we find ourselves in
-               ;; a string escape, we must have deleted the escaped
-               ;; character, and the backslash is behind the point, so
-               ;; backward delete it.
-               (backward-delete-char 1)))
-          ((eq (point) (cdr start+end))
-           ;; If it is the open-quote, delete only if we're also right
-           ;; past the close-quote (i.e. it's empty), and then delete
-           ;; both quotes.  Otherwise we refuse to delete it.
-           (backward-delete-char 1)
-           (delete-char 1)))))
-
-;;;; Killing
-
-(defun paredit-kill (&optional arg)
-  "Kill a line as if with `kill-line', but respecting delimiters.
-In a string, act exactly as `kill-line' but do not kill past the
-  closing string delimiter.
-On a line with no S-expressions on it starting after the point or
-  within a comment, act exactly as `kill-line'.
-Otherwise, kill all S-expressions that start after the point."
-  (interactive "P")
-  (cond (arg (kill-line))
-        ((paredit-in-string-p)
-         (paredit-kill-line-in-string))
-        ((or (paredit-in-comment-p)
-             (save-excursion
-               (paredit-skip-whitespace t (point-at-eol))
-               (or (eq (char-after) ?\; )
-                   (eolp))))
-         ;** Be careful about trailing backslashes.
-         (kill-line))
-        (t (paredit-kill-sexps-on-line))))
-
-(defun paredit-kill-line-in-string ()
-  (if (save-excursion (paredit-skip-whitespace t (point-at-eol))
-                      (eolp))
-      (kill-line)
-    (save-excursion
-      ;; Be careful not to split an escape sequence.
-      (if (paredit-in-string-escape-p)
-          (backward-char))
-      (let ((beginning (point)))
-        (while (not (or (eolp)
-                        (eq (char-after) ?\" )))
-          (forward-char)
-          ;; Skip past escaped characters.
-          (if (eq (char-before) ?\\ )
-              (forward-char)))
-        (kill-region beginning (point))))))
-
-(defun paredit-kill-sexps-on-line ()
-  (if (paredit-in-char-p)               ; Move past the \ and prefix.
-      (backward-char 2))                ; (# in Scheme/CL, ? in elisp)
-  (let ((beginning (point))
-        (eol (point-at-eol)))
-    (let ((end-of-list-p (paredit-forward-sexps-to-kill beginning eol)))
-      ;; If we got to the end of the list and it's on the same line,
-      ;; move backward past the closing delimiter before killing.  (This
-      ;; allows something like killing the whitespace in (    ).)
-      (if end-of-list-p (progn (up-list) (backward-char)))
-      (if kill-whole-line
-          (paredit-kill-sexps-on-whole-line beginning)
-        (kill-region beginning
-                     ;; If all of the S-expressions were on one line,
-                     ;; i.e. we're still on that line after moving past
-                     ;; the last one, kill the whole line, including
-                     ;; any comments; otherwise just kill to the end of
-                     ;; the last S-expression we found.  Be sure,
-                     ;; though, not to kill any closing parentheses.
-                     (if (and (not end-of-list-p)
-                              (eq (point-at-eol) eol))
-                         eol
-                         (point)))))))
-
-;;; Please do not try to understand this code unless you have a VERY
-;;; good reason to do so.  I gave up trying to figure it out well
-;;; enough to explain it, long ago.
-
-(defun paredit-forward-sexps-to-kill (beginning eol)
-  (let ((end-of-list-p nil)
-        (firstp t))
-    ;; Move to the end of the last S-expression that started on this
-    ;; line, or to the closing delimiter if the last S-expression in
-    ;; this list is on the line.
-    (catch 'return
-      (while t
-        ;; This and the `kill-whole-line' business below fix a bug that
-        ;; inhibited any S-expression at the very end of the buffer
-        ;; (with no trailing newline) from being deleted.  It's a
-        ;; bizarre fix that I ought to document at some point, but I am
-        ;; too busy at the moment to do so.
-        (if (and kill-whole-line (eobp)) (throw 'return nil))
-        (save-excursion
-          (paredit-handle-sexp-errors (forward-sexp)
-            (up-list)
-            (setq end-of-list-p (eq (point-at-eol) eol))
-            (throw 'return nil))
-          (if (or (and (not firstp)
-                       (not kill-whole-line)
-                       (eobp))
-                  (paredit-handle-sexp-errors
-                      (progn (backward-sexp) nil)
-                    t)
-                  (not (eq (point-at-eol) eol)))
-              (throw 'return nil)))
-        (forward-sexp)
-        (if (and firstp
-                 (not kill-whole-line)
-                 (eobp))
-            (throw 'return nil))
-        (setq firstp nil)))
-    end-of-list-p))
-
-(defun paredit-kill-sexps-on-whole-line (beginning)
-  (kill-region beginning
-               (or (save-excursion     ; Delete trailing indentation...
-                     (paredit-skip-whitespace t)
-                     (and (not (eq (char-after) ?\; ))
-                          (point)))
-                   ;; ...or just use the point past the newline, if
-                   ;; we encounter a comment.
-                   (point-at-eol)))
-  (cond ((save-excursion (paredit-skip-whitespace nil (point-at-bol))
-                         (bolp))
-         ;; Nothing but indentation before the point, so indent it.
-         (lisp-indent-line))
-        ((eobp) nil)       ; Protect the CHAR-SYNTAX below against NIL.
-        ;; Insert a space to avoid invalid joining if necessary.
-        ((let ((syn-before (char-syntax (char-before)))
-               (syn-after  (char-syntax (char-after))))
-           (or (and (eq syn-before ?\) )            ; Separate opposing
-                    (eq syn-after  ?\( ))           ;   parentheses,
-               (and (eq syn-before ?\" )            ; string delimiter
-                    (eq syn-after  ?\" ))           ;   pairs,
-               (and (memq syn-before '(?_ ?w))      ; or word or symbol
-                    (memq syn-after  '(?_ ?w)))))   ;   constituents.
-         (insert " "))))
-
-;;;;; Killing Words
-
-;;; This is tricky and asymmetrical because backward parsing is
-;;; extraordinarily difficult or impossible, so we have to implement
-;;; killing in both directions by parsing forward.
-
-(defun paredit-forward-kill-word ()
-  "Kill a word forward, skipping over intervening delimiters."
-  (interactive)
-  (let ((beginning (point)))
-    (skip-syntax-forward " -")
-    (let* ((parse-state (paredit-current-parse-state))
-           (state (paredit-kill-word-state parse-state 'char-after)))
-      (while (not (or (eobp)
-                      (eq ?w (char-syntax (char-after)))))
-        (setq parse-state
-              (progn (forward-char 1) (paredit-current-parse-state))
-;;               (parse-partial-sexp (point) (1+ (point))
-;;                                   nil nil parse-state)
-              )
-        (let* ((old-state state)
-               (new-state
-                (paredit-kill-word-state parse-state 'char-after)))
-          (cond ((not (eq old-state new-state))
-                 (setq parse-state
-                       (paredit-kill-word-hack old-state
-                                               new-state
-                                               parse-state))
-                 (setq state
-                       (paredit-kill-word-state parse-state
-                                                'char-after))
-                 (setq beginning (point)))))))
-    (goto-char beginning)
-    (kill-word 1)))
-
-(defun paredit-backward-kill-word ()
-  "Kill a word backward, skipping over any intervening delimiters."
-  (interactive)
-  (if (not (or (bobp)
-               (eq (char-syntax (char-before)) ?w)))
-      (let ((end (point)))
-        (backward-word 1)
-        (forward-word 1)
-        (goto-char (min end (point)))
-        (let* ((parse-state (paredit-current-parse-state))
-               (state
-                (paredit-kill-word-state parse-state 'char-before)))
-          (while (and (< (point) end)
-                      (progn
-                        (setq parse-state
-                              (parse-partial-sexp (point) (1+ (point))
-                                                  nil nil parse-state))
-                        (or (eq state
-                                (paredit-kill-word-state parse-state
-                                                         'char-before))
-                            (progn (backward-char 1) nil)))))
-          (if (and (eq state 'comment)
-                   (eq ?\# (char-after (point)))
-                   (eq ?\| (char-before (point))))
-              (backward-char 1)))))
-  (backward-kill-word 1))
-
-;;; Word-Killing Auxiliaries
-
-(defun paredit-kill-word-state (parse-state adjacent-char-fn)
-  (cond ((paredit-in-comment-p parse-state) 'comment)
-        ((paredit-in-string-p  parse-state) 'string)
-        ((memq (char-syntax (funcall adjacent-char-fn))
-               '(?\( ?\) ))
-         'delimiter)
-        (t 'other)))
-
-;;; This optionally advances the point past any comment delimiters that
-;;; should probably not be touched, based on the last state change and
-;;; the characters around the point.  It returns a new parse state,
-;;; starting from the PARSE-STATE parameter.
-
-(defun paredit-kill-word-hack (old-state new-state parse-state)
-  (cond ((and (not (eq old-state 'comment))
-              (not (eq new-state 'comment))
-              (not (paredit-in-string-escape-p))
-              (eq ?\# (char-before))
-              (eq ?\| (char-after)))
-         (forward-char 1)
-         (paredit-current-parse-state)
-;;          (parse-partial-sexp (point) (1+ (point))
-;;                              nil nil parse-state)
-         )
-        ((and (not (eq old-state 'comment))
-              (eq new-state 'comment)
-              (eq ?\; (char-before)))
-         (skip-chars-forward ";")
-         (paredit-current-parse-state)
-;;          (parse-partial-sexp (point) (save-excursion
-;;                                        (skip-chars-forward ";"))
-;;                              nil nil parse-state)
-         )
-        (t parse-state)))
-
-;;;; Cursor and Screen Movement
-
-(eval-and-compile
-  (defmacro defun-saving-mark (name bvl doc &rest body)
-    `(defun ,name ,bvl
-       ,doc
-       ,(xcond ((paredit-xemacs-p)
-                '(interactive "_"))
-               ((paredit-gnu-emacs-p)
-                '(interactive)))
-       ,@body)))
-
-(defun-saving-mark paredit-forward ()
-  "Move forward an S-expression, or up an S-expression forward.
-If there are no more S-expressions in this one before the closing
-  delimiter, move past that closing delimiter; otherwise, move forward
-  past the S-expression following the point."
-  (paredit-handle-sexp-errors
-      (forward-sexp)
-    ;++ Is it necessary to use UP-LIST and not just FORWARD-CHAR?
-    (if (paredit-in-string-p) (forward-char) (up-list))))
-
-(defun-saving-mark paredit-backward ()
-  "Move backward an S-expression, or up an S-expression backward.
-If there are no more S-expressions in this one before the opening
-  delimiter, move past that opening delimiter backward; otherwise, move
-  move backward past the S-expression preceding the point."
-  (paredit-handle-sexp-errors
-      (backward-sexp)
-    (if (paredit-in-string-p) (backward-char) (backward-up-list))))
-
-;;; Why is this not in lisp.el?
-
-(defun backward-down-list (&optional arg)
-  "Move backward and descend into one level of parentheses.
-With ARG, do this that many times.
-A negative argument means move forward but still descend a level."
-  (interactive "p")
-  (down-list (- (or arg 1))))
-
-;;; Thanks to Marco Baringer for suggesting & writing this function.
-
-(defun paredit-recentre-on-sexp (&optional n)
-  "Recentre the screen on the S-expression following the point.
-With a prefix argument N, encompass all N S-expressions forward."
-  (interactive "P")
-  (save-excursion
-    (forward-sexp n)
-    (let ((end-point (point)))
-      (backward-sexp n)
-      (let* ((start-point (point))
-             (start-line (count-lines (point-min) (point)))
-             (lines-on-sexps (count-lines start-point end-point)))
-        (goto-line (+ start-line (/ lines-on-sexps 2)))
-        (recenter)))))
-
-;;;; Depth-Changing Commands:  Wrapping, Splicing, & Raising
-
-(defun paredit-wrap-sexp (&optional n open close)
-  "Wrap the following S-expression in a list.
-If a prefix argument N is given, wrap N S-expressions.
-Automatically indent the newly wrapped S-expression.
-As a special case, if the point is at the end of a list, simply insert
-  a pair of parentheses, rather than insert a lone opening parenthesis
-  and then signal an error, in the interest of preserving structure."
-  (interactive "P")
-  (let ((open (or open ?\())
-        (close (or close ?\))))
-   (paredit-handle-sexp-errors
-       (paredit-insert-pair (or n
-                                (and (not (paredit-region-active-p))
-                                     1))
-                            open close
-                            'goto-char)
-     (insert close)
-     (backward-char))
-   (save-excursion (backward-up-list) (indent-sexp))))
-
-;;; Thanks to Marco Baringer for the suggestion of a prefix argument
-;;; for PAREDIT-SPLICE-SEXP.  (I, Taylor R. Campbell, however, still
-;;; implemented it, in case any of you lawyer-folk get confused by the
-;;; remark in the top of the file about explicitly noting code written
-;;; by other people.)
-
-(defun paredit-splice-sexp (&optional arg)
-  "Splice the list that the point is on by removing its delimiters.
-With a prefix argument as in `C-u', kill all S-expressions backward in
-  the current list before splicing all S-expressions forward into the
-  enclosing list.
-With two prefix arguments as in `C-u C-u', kill all S-expressions
-  forward in the current list before splicing all S-expressions
-  backward into the enclosing list.
-With a numerical prefix argument N, kill N S-expressions backward in
-  the current list before splicing the remaining S-expressions into the
-  enclosing list.  If N is negative, kill forward.
-This always creates a new entry on the kill ring."
-  (interactive "P")
-  (save-excursion
-    (paredit-kill-surrounding-sexps-for-splice arg)
-    (backward-up-list)                  ; Go up to the beginning...
-    (save-excursion
-      (forward-sexp)                    ; Go forward an expression, to
-      (backward-delete-char 1))         ;   delete the end delimiter.
-    (delete-char 1)                     ; ...to delete the open char.
-    (paredit-ignore-sexp-errors
-      (backward-up-list)                ; Reindent, now that the
-      (indent-sexp))))                  ;   structure has changed.
-
-(defun paredit-kill-surrounding-sexps-for-splice (arg)
-  (cond ((paredit-in-string-p) (error "Splicing illegal in strings."))
-        ((or (not arg) (eq arg 0)) nil)
-        ((or (numberp arg) (eq arg '-))
-         ;; Kill ARG S-expressions before/after the point by saving
-         ;; the point, moving across them, and killing the region.
-         (let* ((arg (if (eq arg '-) -1 arg))
-                (saved (paredit-point-at-sexp-boundary (- arg))))
-           (paredit-ignore-sexp-errors (backward-sexp arg))
-           (kill-region-new saved (point))))
-        ((consp arg)
-         (let ((v (car arg)))
-           (if (= v 4)                  ; one prefix argument
-               ;; Move backward until we hit the open paren; then
-               ;; kill that selected region.
-               (let ((end (paredit-point-at-sexp-start)))
-                 (paredit-ignore-sexp-errors
-                   (while (not (bobp))
-                     (backward-sexp)))
-                 (kill-region-new (point) end))
-               ;; Move forward until we hit the close paren; then
-               ;; kill that selected region.
-               (let ((beginning (paredit-point-at-sexp-end)))
-                 (paredit-ignore-sexp-errors
-                   (while (not (eobp))
-                     (forward-sexp)))
-                 (kill-region-new beginning (point))))))
-        (t (error "Bizarre prefix argument: %s" arg))))
-
-(defun paredit-splice-sexp-killing-backward (&optional n)
-  "Splice the list the point is on by removing its delimiters, and
-  also kill all S-expressions before the point in the current list.
-With a prefix argument N, kill only the preceding N S-expressions."
-  (interactive "P")
-  (paredit-splice-sexp (if n
-                           (prefix-numeric-value n)
-                           '(4))))
-
-(defun paredit-splice-sexp-killing-forward (&optional n)
-  "Splice the list the point is on by removing its delimiters, and
-  also kill all S-expressions after the point in the current list.
-With a prefix argument N, kill only the following N S-expressions."
-  (interactive "P")
-  (paredit-splice-sexp (if n
-                           (- (prefix-numeric-value n))
-                           '(16))))
-
-(defun paredit-raise-sexp (&optional n)
-  "Raise the following S-expression in a tree, deleting its siblings.
-With a prefix argument N, raise the following N S-expressions.  If N
-  is negative, raise the preceding N S-expressions."
-  (interactive "p")
-  ;; Select the S-expressions we want to raise in a buffer substring.
-  (let* ((bound (save-excursion (forward-sexp n) (point)))
-         (sexps (save-excursion         ;++ Is this necessary?
-                  (if (and n (< n 0))
-                      (buffer-substring bound
-                                        (paredit-point-at-sexp-end))
-                      (buffer-substring (paredit-point-at-sexp-start)
-                                        bound)))))
-    ;; Move up to the list we're raising those S-expressions out of and
-    ;; delete it.
-    (backward-up-list)
-    (delete-region (point) (save-excursion (forward-sexp) (point)))
-    (save-excursion (insert sexps))     ; Insert & reindent the sexps.
-    (save-excursion (let ((n (abs (or n 1))))
-                      (while (> n 0)
-                        (paredit-forward-and-indent)
-                        (setq n (1- n)))))))
-
-;;;; Slurpage & Barfage
-
-(defun paredit-forward-slurp-sexp ()
-  "Add the S-expression following the current list into that list
-  by moving the closing delimiter.
-Automatically reindent the newly slurped S-expression with respect to
-  its new enclosing form.
-If in a string, move the opening double-quote forward by one
-  S-expression and escape any intervening characters as necessary,
-  without altering any indentation or formatting."
-  (interactive)
-  (save-excursion
-    (cond ((or (paredit-in-comment-p)
-               (paredit-in-char-p))
-           (error "Invalid context for slurpage"))
-          ((paredit-in-string-p)
-           (paredit-forward-slurp-into-string))
-          (t
-           (paredit-forward-slurp-into-list)))))
-
-(defun paredit-forward-slurp-into-list ()
-  (up-list)                             ; Up to the end of the list to
-  (let ((close (char-before)))          ;   save and delete the closing
-    (backward-delete-char 1)            ;   delimiter.
-    (catch 'return                      ; Go to the end of the desired
-      (while t                          ;   S-expression, going up a
-        (paredit-handle-sexp-errors     ;   list if it's not in this,
-            (progn (paredit-forward-and-indent)
-                   (throw 'return nil))
-          (insert close)
-          (up-list)
-          (setq close (char-before))
-          (backward-delete-char 1))))
-    (insert close)))                    ; to insert that delimiter.
-
-(defun paredit-forward-slurp-into-string ()
-  (goto-char (1+ (cdr (paredit-string-start+end-points))))
-  ;; Signal any errors that we might get first, before mucking with the
-  ;; buffer's contents.
-  (save-excursion (forward-sexp))
-  (let ((close (char-before)))
-    (backward-delete-char 1)
-    (paredit-forward-for-quote (save-excursion (forward-sexp) (point)))
-    (insert close)))
-
-(defun paredit-forward-barf-sexp ()
-  "Remove the last S-expression in the current list from that list
-  by moving the closing delimiter.
-Automatically reindent the newly barfed S-expression with respect to
-  its new enclosing form."
-  (interactive)
-  (save-excursion
-    (up-list)                           ; Up to the end of the list to
-    (let ((close (char-before)))        ;   save and delete the closing
-      (backward-delete-char 1)          ;   delimiter.
-      (paredit-ignore-sexp-errors       ; Go back to where we want to
-        (backward-sexp))                ;   insert the delimiter.
-      (paredit-skip-whitespace nil)     ; Skip leading whitespace.
-      (cond ((bobp)
-             (error "Barfing all subexpressions with no open-paren?"))
-            ((paredit-in-comment-p)     ; Don't put the close-paren in
-             (newline-and-indent)))     ;   a comment.
-      (insert close))
-    ;; Reindent all of the newly barfed S-expressions.
-    (paredit-forward-and-indent)))
-
-(defun paredit-backward-slurp-sexp ()
-  "Add the S-expression preceding the current list into that list
-  by moving the closing delimiter.
-Automatically reindent the whole form into which new S-expression was
-  slurped.
-If in a string, move the opening double-quote backward by one
-  S-expression and escape any intervening characters as necessary,
-  without altering any indentation or formatting."
-  (interactive)
-  (save-excursion
-    (cond ((or (paredit-in-comment-p)
-               (paredit-in-char-p))
-           (error "Invalid context for slurpage"))
-          ((paredit-in-string-p)
-           (paredit-backward-slurp-into-string))
-          (t
-           (paredit-backward-slurp-into-list)))))
-
-(defun paredit-backward-slurp-into-list ()
-  (backward-up-list)
-  (let ((open (char-after)))
-    (delete-char 1)
-    (catch 'return
-      (while t
-        (paredit-handle-sexp-errors
-            (progn (backward-sexp)
-                   (throw 'return nil))
-          (insert open)
-          (backward-char 1)
-          (backward-up-list)
-          (setq open (char-after))
-          (delete-char 1))))
-    (insert open))
-  ;; Reindent the line at the beginning of wherever we inserted the
-  ;; opening parenthesis, and then indent the whole S-expression.
-  (backward-up-list)
-  (lisp-indent-line)
-  (indent-sexp))
-
-(defun paredit-backward-slurp-into-string ()
-  (goto-char (car (paredit-string-start+end-points)))
-  ;; Signal any errors that we might get first, before mucking with the
-  ;; buffer's contents.
-  (save-excursion (backward-sexp))
-  (let ((open (char-after))
-        (target (point)))
-    (message "open = %S" open)
-    (delete-char 1)
-    (backward-sexp)
-    (insert open)
-    (paredit-forward-for-quote target)))
-
-(defun paredit-backward-barf-sexp ()
-  "Remove the first S-expression in the current list from that list
-  by moving the closing delimiter.
-Automatically reindent the barfed S-expression and the form from which
-  it was barfed."
-  (interactive)
-  (save-excursion
-    (backward-up-list)
-    (let ((open (char-after)))
-      (delete-char 1)
-      (paredit-ignore-sexp-errors
-        (paredit-forward-and-indent))
-      (while (progn (paredit-skip-whitespace t)
-                    (eq (char-after) ?\; ))
-        (forward-line 1))
-      (if (eobp)
-          (error
-           "Barfing all subexpressions with no close-paren?"))
-      ;** Don't use `insert' here.  Consider, e.g., barfing from
-      ;**   (foo|)
-      ;** and how `save-excursion' works.
-      (insert-before-markers open))
-    (backward-up-list)
-    (lisp-indent-line)
-    (indent-sexp)))
-
-;;;; Splitting & Joining
-
-(defun paredit-split-sexp ()
-  "Split the list or string the point is on into two."
-  (interactive)
-  (cond ((paredit-in-string-p)
-         (insert "\"")
-         (save-excursion (insert " \"")))
-        ((or (paredit-in-comment-p)
-             (paredit-in-char-p))
-         (error "Invalid context for `paredit-split-sexp'"))
-        (t (let ((open  (save-excursion (backward-up-list)
-                                        (char-after)))
-                 (close (save-excursion (up-list)
-                                        (char-before))))
-             (delete-horizontal-space)
-             (insert close)
-             (save-excursion (insert ?\ )
-                             (insert open)
-                             (backward-char)
-                             (indent-sexp))))))
-
-(defun paredit-join-sexps ()
-  "Join the S-expressions adjacent on either side of the point.
-Both must be lists, strings, or atoms; error if there is a mismatch."
-  (interactive)
-  ;++ How ought this to handle comments intervening symbols or strings?
-  (save-excursion
-    (if (or (paredit-in-comment-p)
-            (paredit-in-string-p)
-            (paredit-in-char-p))
-        (error "Invalid context in which to join S-expressions.")
-      (let ((left-point  (save-excursion (paredit-point-at-sexp-end)))
-            (right-point (save-excursion
-                           (paredit-point-at-sexp-start))))
-        (let ((left-char (char-before left-point))
-              (right-char (char-after right-point)))
-          (let ((left-syntax (char-syntax left-char))
-                (right-syntax (char-syntax right-char)))
-            (cond ((>= left-point right-point)
-                   (error "Can't join a datum with itself."))
-                  ((and (eq left-syntax  ?\) )
-                        (eq right-syntax ?\( )
-                        (eq left-char (matching-paren right-char))
-                        (eq right-char (matching-paren left-char)))
-                   ;; Leave intermediate formatting alone.
-                   (goto-char right-point)
-                   (delete-char 1)
-                   (goto-char left-point)
-                   (backward-delete-char 1)
-                   (backward-up-list)
-                   (indent-sexp))
-                  ((and (eq left-syntax  ?\" )
-                        (eq right-syntax ?\" ))
-                   ;; Delete any intermediate formatting.
-                   (delete-region (1- left-point)
-                                  (1+ right-point)))
-                  ((and (memq left-syntax  '(?w ?_)) ; Word or symbol
-                        (memq right-syntax '(?w ?_)))
-                   (delete-region left-point right-point))
-                  (t
-                   (error "Mismatched S-expressions to join.")))))))))
-
-;;;; Utilities
-
-(defun paredit-in-string-escape-p ()
-  "True if the point is on a character escape of a string.
-This is true only if the character is preceded by an odd number of
-  backslashes.
-This assumes that `paredit-in-string-p' has already returned true."
-  (let ((oddp nil))
-    (save-excursion
-      (while (eq (char-before) ?\\ )
-        (setq oddp (not oddp))
-        (backward-char)))
-    oddp))
-
-(defun paredit-in-char-p (&optional arg)
-  "True if the point is immediately after a character literal.
-A preceding escape character, not preceded by another escape character,
-  is considered a character literal prefix.  (This works for elisp,
-  Common Lisp, and Scheme.)
-Assumes that `paredit-in-string-p' is false, so that it need not handle
-  long sequences of preceding backslashes in string escapes.  (This
-  assumes some other leading character token -- ? in elisp, # in Scheme
-  and Common Lisp.)"
-  (let ((arg (or arg (point))))
-    (and (eq (char-before arg) ?\\ )
-         (not (eq (char-before (1- arg)) ?\\ )))))
-
-(defun paredit-forward-and-indent ()
-  "Move forward an S-expression, indenting it fully.
-Indent with `lisp-indent-line' and then `indent-sexp'."
-  (forward-sexp)                        ; Go forward, and then find the
-  (save-excursion                       ;   beginning of this next
-    (backward-sexp)                     ;   S-expression.
-    (lisp-indent-line)                  ; Indent its opening line, and
-    (indent-sexp)))                     ;   the rest of it.
-
-(defun paredit-skip-whitespace (trailing-p &optional limit)
-  "Skip past any whitespace, or until the point LIMIT is reached.
-If TRAILING-P is nil, skip leading whitespace; otherwise, skip trailing
-  whitespace."
-  (funcall (if trailing-p 'skip-chars-forward 'skip-chars-backward)
-           " \t\n"  ; This should skip using the syntax table, but LF
-           limit))    ; is a comment end, not newline, in Lisp mode.
-
-(defalias 'paredit-region-active-p
-  (xcond ((paredit-xemacs-p) 'region-active-p)
-         ((paredit-gnu-emacs-p)
-          (lambda ()
-            (and mark-active transient-mark-mode)))))
-
-(defun kill-region-new (start end)
-  "Kill the region between START and END.
-Do not append to any current kill, and
- do not let the next kill append to this one."
-  (interactive "r")                     ;Eh, why not?
-  ;; KILL-REGION sets THIS-COMMAND to tell the next kill that the last
-  ;; command was a kill.  It also checks LAST-COMMAND to see whether it
-  ;; should append.  If we bind these locally, any modifications to
-  ;; THIS-COMMAND will be masked, and it will not see LAST-COMMAND to
-  ;; indicate that it should append.
-  (let ((this-command nil)
-        (last-command nil))
-    (kill-region start end)))
-
-;;;;; S-expression Parsing Utilities
-
-;++ These routines redundantly traverse S-expressions a great deal.
-;++ If performance issues arise, this whole section will probably have
-;++ to be refactored to preserve the state longer, like paredit.scm
-;++ does, rather than to traverse the definition N times for every key
-;++ stroke as it presently does.
-
-(defun paredit-current-parse-state ()
-  "Return parse state of point from beginning of defun."
-  (let ((point (point)))
-    (beginning-of-defun)
-    ;; Calling PARSE-PARTIAL-SEXP will advance the point to its second
-    ;; argument (unless parsing stops due to an error, but we assume it
-    ;; won't in paredit-mode).
-    (parse-partial-sexp (point) point)))
-
-(defun paredit-in-string-p (&optional state)
-  "True if the parse state is within a double-quote-delimited string.
-If no parse state is supplied, compute one from the beginning of the
-  defun to the point."
-  ;; 3. non-nil if inside a string (the terminator character, really)
-  (and (nth 3 (or state (paredit-current-parse-state)))
-       t))
-
-(defun paredit-string-start+end-points (&optional state)
-  "Return a cons of the points of open and close quotes of the string.
-The string is determined from the parse state STATE, or the parse state
-  from the beginning of the defun to the point.
-This assumes that `paredit-in-string-p' has already returned true, i.e.
-  that the point is already within a string."
-  (save-excursion
-    ;; 8. character address of start of comment or string; nil if not
-    ;;    in one
-    (let ((start (nth 8 (or state (paredit-current-parse-state)))))
-      (goto-char start)
-      (forward-sexp 1)
-      (cons start (1- (point))))))
-
-(defun paredit-in-comment-p (&optional state)
-  "True if parse state STATE is within a comment.
-If no parse state is supplied, compute one from the beginning of the
-  defun to the point."
-  ;; 4. nil if outside a comment, t if inside a non-nestable comment,
-  ;;    else an integer (the current comment nesting)
-  (and (nth 4 (or state (paredit-current-parse-state)))
-       t))
-
-(defun paredit-point-at-sexp-boundary (n)
-  (cond ((< n 0) (paredit-point-at-sexp-start))
-        ((= n 0) (point))
-        ((> n 0) (paredit-point-at-sexp-end))))
-
-(defun paredit-point-at-sexp-start ()
-  (forward-sexp)
-  (backward-sexp)
-  (point))
-
-(defun paredit-point-at-sexp-end ()
-  (backward-sexp)
-  (forward-sexp)
-  (point))
-
-;;;; Initialization
-
-(paredit-define-keys)
-(paredit-annotate-mode-with-examples)
-(paredit-annotate-functions-with-examples)
-
-(provide 'paredit)
deleted file mode 100644
--- a/.elisp/pycomplete.el
+++ /dev/null
@@ -1,50 +0,0 @@
-;;; Complete symbols at point using Pymacs.
-
-;; Copyright (C) 2007  Skip Montanaro
-
-;; Author:     Skip Montanaro
-;; Maintainer: skip@pobox.com
-;; Created:    Oct 2004
-;; Keywords:   python pymacs emacs
-
-;; This software is provided as-is, without express or implied warranty.
-;; Permission to use, copy, modify, distribute or sell this software,
-;; without fee, for any purpose and by any individual or organization, is
-;; hereby granted, provided that the above copyright notice and this
-;; paragraph appear in all copies.
-
-;; Along with pycomplete.py this file allows programmers to complete Python
-;; symbols within the current buffer.  See pycomplete.py for the Python side
-;; of things and a short description of what to expect.
-
-(require 'pymacs)
-(require 'python-mode)
-
-(pymacs-load "pycomplete")
-
-(defun py-complete ()
-  (interactive)
-  (let ((pymacs-forget-mutability t)) 
-    (insert (pycomplete-pycomplete (py-symbol-near-point)
-				   (py-find-global-imports)))))
-
-(defun py-find-global-imports ()
-  (save-excursion
-    (let (first-class-or-def imports)
-      (goto-char (point-min))
-      (setq first-class-or-def
-	    (re-search-forward "^ *\\(def\\|class\\) " nil t))
-      (goto-char (point-min))
-      (setq imports nil)
-      (while (re-search-forward
-	      "^\\(import \\|from \\([A-Za-z_][A-Za-z_0-9]*\\) import \\).*"
-	      nil t)
-	(setq imports (append imports
-			      (list (buffer-substring
-				     (match-beginning 0)
-				     (match-end 0))))))
-      imports)))
-
-(define-key py-mode-map "\M-\C-i"  'py-complete)
-
-(provide 'pycomplete)
deleted file mode 100644
--- a/.elisp/pycomplete.py
+++ /dev/null
@@ -1,110 +0,0 @@
-
-"""
-Python dot expression completion using Pymacs.
-
-This almost certainly needs work, but if you add
-
-    (require 'pycomplete)
-
-to your .xemacs/init.el file (untried w/ GNU Emacs so far) and have Pymacs
-installed, when you hit M-TAB it will try to complete the dot expression
-before point.  For example, given this import at the top of the file:
-
-    import time
-
-typing "time.cl" then hitting M-TAB should complete "time.clock".
-
-This is unlikely to be done the way Emacs completion ought to be done, but
-it's a start.  Perhaps someone with more Emacs mojo can take this stuff and
-do it right.
-
-See pycomplete.el for the Emacs Lisp side of things.
-"""
-
-# Author:     Skip Montanaro
-# Maintainer: skip@pobox.com
-# Created:    Oct 2004
-# Keywords:   python pymacs emacs
-
-# This software is provided as-is, without express or implied warranty.
-# Permission to use, copy, modify, distribute or sell this software, without
-# fee, for any purpose and by any individual or organization, is hereby
-# granted, provided that the above copyright notice and this paragraph
-# appear in all copies.
-
-# Along with pycomplete.el this file allows programmers to complete Python
-# symbols within the current buffer.
-
-import sys
-import os.path
-
-try:
-    x = set
-except NameError:
-    from sets import Set as set
-else:
-    del x
-
-def get_all_completions(s, imports=None):
-    """Return contextual completion of s (string of >= zero chars).
-
-    If given, imports is a list of import statements to be executed first.
-    """
-    locald = {}
-    if imports is not None:
-        for stmt in imports:
-            try:
-                exec stmt in globals(), locald
-            except TypeError:
-                raise TypeError, "invalid type: %s" % stmt
-
-    dots = s.split(".")
-    if not s or len(dots) == 1:
-        keys = set()
-        keys.update(locald.keys())
-        keys.update(globals().keys())
-        import __builtin__
-        keys.update(dir(__builtin__))
-        keys = list(keys)
-        keys.sort()
-        if s:
-            return [k for k in keys if k.startswith(s)]
-        else:
-            return keys
-
-    sym = None
-    for i in range(1, len(dots)):
-        s = ".".join(dots[:i])
-        try:
-            sym = eval(s, globals(), locald)
-        except NameError:
-            try:
-                sym = __import__(s, globals(), locald, [])
-            except ImportError:
-                return []
-    if sym is not None:
-        s = dots[-1]
-        return [k for k in dir(sym) if k.startswith(s)]
-
-def pycomplete(s, imports=None):
-    completions = get_all_completions(s, imports)
-    dots = s.split(".")
-    return os.path.commonprefix([k[len(dots[-1]):] for k in completions])
-
-if __name__ == "__main__":
-    print "<empty> ->", pycomplete("")
-    print "sys.get ->", pycomplete("sys.get")
-    print "sy ->", pycomplete("sy")
-    print "sy (sys in context) ->", pycomplete("sy", imports=["import sys"])
-    print "foo. ->", pycomplete("foo.")
-    print "Enc (email * imported) ->",
-    print pycomplete("Enc", imports=["from email import *"])
-    print "E (email * imported) ->",
-    print pycomplete("E", imports=["from email import *"])
-
-    print "Enc ->", pycomplete("Enc")
-    print "E ->", pycomplete("E")
-
-# Local Variables :
-# pymacs-auto-reload : t
-# End :
deleted file mode 100644
--- a/.elisp/pymacs.el
+++ /dev/null
@@ -1,688 +0,0 @@
-;;; Interface between Emacs Lisp and Python - Lisp part.    -*- emacs-lisp -*-
-;;; Copyright © 2001, 2002, 2003 Progiciels Bourbeau-Pinard inc.
-;;; François Pinard <pinard@iro.umontreal.ca>, 2001.
-
-;;; This program is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; This program is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;;; GNU General Public License for more details.
-;;;
-;;; You should have received a copy of the GNU General Public License
-;;; along with this program; if not, write to the Free Software Foundation,
-;;; Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.  */
-
-;;; Portability stunts.
-
-(defvar pymacs-use-hash-tables
-  (and (fboundp 'make-hash-table) (fboundp 'gethash) (fboundp 'puthash))
-  "Set to t if hash tables are available.")
-
-(eval-and-compile
-
-  (if (fboundp 'multibyte-string-p)
-      (defalias 'pymacs-multibyte-string-p 'multibyte-string-p)
-    (defun pymacs-multibyte-string-p (string)
-      "Tell XEmacs if STRING should be handled as multibyte."
-      (not (equal (find-charset-string string) '(ascii))))))
-
-(defalias 'pymacs-report-error (symbol-function 'error))
-
-;;; Published variables and functions.
-
-(defvar pymacs-load-path nil
-  "List of additional directories to search for Python modules.
-The directories listed will be searched first, in the order given.")
-
-(defvar pymacs-trace-transit '(5000 . 30000)
-  "Keep the communication buffer growing, for debugging.
-When this variable is nil, the `*Pymacs*' communication buffer gets erased
-before each communication round-trip.  Setting it to `t' guarantees that
-the full communication is saved, which is useful for debugging.
-It could also be given as (KEEP . LIMIT): whenever the buffer exceeds LIMIT
-bytes, it is reduced to approximately KEEP bytes.")
-
-(defvar pymacs-forget-mutability nil
-  "Transmit copies to Python instead of Lisp handles, as much as possible.
-When this variable is nil, most mutable objects are transmitted as handles.
-This variable is meant to be temporarily rebound to force copies.")
-
-(defvar pymacs-mutable-strings nil
-  "Prefer transmitting Lisp strings to Python as handles.
-When this variable is nil, strings are transmitted as copies, and the
-Python side thus has no way for modifying the original Lisp strings.
-This variable is ignored whenever `forget-mutability' is set.")
-
-(defvar pymacs-timeout-at-start 30
-  "Maximum reasonable time, in seconds, for starting the Pymacs helper.
-A machine should be pretty loaded before one needs to increment this.")
-
-(defvar pymacs-timeout-at-reply 5
-  "Expected maximum time, in seconds, to get the first line of a reply.
-The status of the Pymacs helper is checked at every such timeout.")
-
-(defvar pymacs-timeout-at-line 2
-  "Expected maximum time, in seconds, to get another line of a reply.
-The status of the Pymacs helper is checked at every such timeout.")
-
-(defvar pymacs-dreadful-zombies nil
-  "If zombies should trigger hard errors, whenever they get called.
-If `nil', calling a zombie will merely produce a diagnostic message.")
-
-(defun pymacs-load (module &optional prefix noerror)
-  "Import the Python module named MODULE into Emacs.
-Each function in the Python module is made available as an Emacs function.
-The Lisp name of each function is the concatenation of PREFIX with
-the Python name, in which underlines are replaced by dashes.  If PREFIX is
-not given, it defaults to MODULE followed by a dash.
-If NOERROR is not nil, do not raise error when the module is not found."
-  (interactive
-   (let* ((module (read-string "Python module? "))
-          (default (concat (car (last (split-string module "\\."))) "-"))
-          (prefix (read-string (format "Prefix? [%s] " default)
-                               nil nil default)))
-     (list module prefix)))
-  (message "Pymacs loading %s..." module)
-  (let ((lisp-code (pymacs-call "pymacs_load_helper" module prefix)))
-    (cond (lisp-code (let ((result (eval lisp-code)))
-                       (message "Pymacs loading %s...done" module)
-                       result))
-          (noerror (message "Pymacs loading %s...failed" module) nil)
-          (t (pymacs-report-error "Pymacs loading %s...failed" module)))))
-
-(defun pymacs-eval (text)
-  "Compile TEXT as a Python expression, and return its value."
-  (interactive "sPython expression? ")
-  (let ((value (pymacs-serve-until-reply "eval" `(princ ,text))))
-    (when (interactive-p)
-      (message "%S" value))
-    value))
-
-(defun pymacs-exec (text)
-  "Compile and execute TEXT as a sequence of Python statements.
-This functionality is experimental, and does not appear to be useful."
-  (interactive "sPython statements? ")
-  (let ((value (pymacs-serve-until-reply "exec" `(princ ,text))))
-    (when (interactive-p)
-      (message "%S" value))
-    value))
-
-(defun pymacs-call (function &rest arguments)
-  "Return the result of calling a Python function FUNCTION over ARGUMENTS.
-FUNCTION is a string denoting the Python function, ARGUMENTS are separate
-Lisp expressions, one per argument.  Immutable Lisp constants are converted
-to Python equivalents, other structures are converted into Lisp handles."
-  (pymacs-serve-until-reply
-   "eval" `(pymacs-print-for-apply ',function ',arguments)))
-
-(defun pymacs-apply (function arguments)
-  "Return the result of calling a Python function FUNCTION over ARGUMENTS.
-FUNCTION is a string denoting the Python function, ARGUMENTS is a list of
-Lisp expressions.  Immutable Lisp constants are converted to Python
-equivalents, other structures are converted into Lisp handles."
-  (pymacs-serve-until-reply
-   "eval" `(pymacs-print-for-apply ',function ',arguments)))
-
-;;; Integration details.
-
-;; Python functions and modules should ideally look like Lisp functions and
-;; modules.  This page tries to increase the integration seamlessness.
-
-(defadvice documentation (around pymacs-ad-documentation activate)
-  ;; Integration of doc-strings.
-  (let* ((reference (pymacs-python-reference function))
-         (python-doc (when reference
-                       (pymacs-eval (format "doc_string(%s)" reference)))))
-    (if (or reference python-doc)
-        (setq ad-return-value
-              (concat
-               "It interfaces to a Python function.\n\n"
-               (when python-doc
-                 (if raw python-doc (substitute-command-keys python-doc)))))
-      ad-do-it)))
-
-(defun pymacs-python-reference (object)
-  ;; Return the text reference of a Python object if possible, else nil.
-  (when (functionp object)
-    (let* ((definition (indirect-function object))
-           (body (and (pymacs-proper-list-p definition)
-                      (> (length definition) 2)
-                      (eq (car definition) 'lambda)
-                      (cddr definition))))
-      (when (and body (listp (car body)) (eq (caar body) 'interactive))
-        ;; Skip the interactive specification of a function.
-        (setq body (cdr body)))
-      (when (and body
-                 ;; Advised functions start with a string.
-                 (not (stringp (car body)))
-                 ;; Python trampolines hold exactly one expression.
-                 (= (length body) 1))
-        (let ((expression (car body)))
-          ;; EXPRESSION might now hold something like:
-          ;;    (pymacs-apply (quote (pymacs-python . N)) ARGUMENT-LIST)
-          (when (and (pymacs-proper-list-p expression)
-                     (= (length expression) 3)
-                     (eq (car expression) 'pymacs-apply)
-                     (eq (car (cadr expression)) 'quote))
-            (setq object (cadr (cadr expression))))))))
-  (when (eq (car-safe object) 'pymacs-python)
-    (format "python[%d]" (cdr object))))
-
-;; The following functions are experimental -- they are not satisfactory yet.
-
-(defun pymacs-file-handler (operation &rest arguments)
-  ;; Integration of load-file, autoload, etc.
-  ;; Emacs might want the contents of some `MODULE.el' which does not exist,
-  ;; while there is a `MODULE.py' or `MODULE.pyc' file in the same directory.
-  ;; The goal is to generate a virtual contents for this `MODULE.el' file, as
-  ;; a set of Lisp trampoline functions to the Python module functions.
-  ;; Python modules can then be loaded or autoloaded as if they were Lisp.
-  (cond ((and (eq operation 'file-readable-p)
-              (let ((module (substring (car arguments) 0 -3)))
-                (or (pymacs-file-force operation arguments)
-                    (file-readable-p (concat module ".py"))
-                    (file-readable-p (concat module ".pyc"))))))
-        ((and (eq operation 'load)
-              (not (pymacs-file-force
-                    'file-readable-p (list (car arguments))))
-              (file-readable-p (car arguments)))
-         (let ((lisp-code (pymacs-call "pymacs_load_helper"
-                                       (substring (car arguments) 0 -3)
-                                       nil)))
-           (unless lisp-code
-             (pymacs-report-error "Python import error"))
-           (eval lisp-code)))
-        ((and (eq operation 'insert-file-contents)
-              (not (pymacs-file-force
-                    'file-readable-p (list (car arguments))))
-              (file-readable-p (car arguments)))
-         (let ((lisp-code (pymacs-call "pymacs_load_helper"
-                                       (substring (car arguments) 0 -3)
-                                       nil)))
-           (unless lisp-code
-             (pymacs-report-error "Python import error"))
-           (insert (prin1-to-string lisp-code))))
-        (t (pymacs-file-force operation arguments))))
-
-(defun pymacs-file-force (operation arguments)
-  ;; Bypass the file handler.
-  (let ((inhibit-file-name-handlers
-         (cons 'pymacs-file-handler
-               (and (eq inhibit-file-name-operation operation)
-                    inhibit-file-name-handlers)))
-        (inhibit-file-name-operation operation))
-    (apply operation arguments)))
-
-;(add-to-list 'file-name-handler-alist '("\\.el\\'" . pymacs-file-handler))
-
-;;; Gargabe collection of Python IDs.
-
-;; Python objects which have no Lisp representation are allocated on the
-;; Python side as `python[INDEX]', and INDEX is transmitted to Emacs, with
-;; the value to use on the Lisp side for it.  Whenever Lisp does not need a
-;; Python object anymore, it should be freed on the Python side.  The
-;; following variables and functions are meant to fill this duty.
-
-(defvar pymacs-used-ids nil
-  "List of received IDs, currently allocated on the Python side.")
-
-(defvar pymacs-weak-hash nil
-  "Weak hash table, meant to find out which IDs are still needed.")
-
-(defvar pymacs-gc-wanted nil
-  "Flag if it is time to clean up unused IDs on the Python side.")
-
-(defvar pymacs-gc-running nil
-  "Flag telling that a Pymacs garbage collection is in progress.")
-
-(defvar pymacs-gc-timer nil
-  "Timer to trigger Pymacs garbage collection at regular time intervals.
-The timer is used only if `post-gc-hook' is not available.")
-
-(defun pymacs-schedule-gc (&optional xemacs-list)
-  (unless pymacs-gc-running
-    (setq pymacs-gc-wanted t)))
-
-(defun pymacs-garbage-collect ()
-  ;; Clean up unused IDs on the Python side.
-  (when pymacs-use-hash-tables
-    (let ((pymacs-gc-running t)
-          (pymacs-forget-mutability t)
-          (ids pymacs-used-ids)
-          used-ids unused-ids)
-      (while ids
-        (let ((id (car ids)))
-          (setq ids (cdr ids))
-          (if (gethash id pymacs-weak-hash)
-              (setq used-ids (cons id used-ids))
-            (setq unused-ids (cons id unused-ids)))))
-      (setq pymacs-used-ids used-ids
-            pymacs-gc-wanted nil)
-      (when unused-ids
-        (pymacs-apply "free_python" unused-ids)))))
-
-(defun pymacs-defuns (arguments)
-  ;; Take one argument, a list holding a number of items divisible by 3.  The
-  ;; first argument is an INDEX, the second is a NAME, the third is the
-  ;; INTERACTION specification, and so forth.  Register Python INDEX with a
-  ;; function with that NAME and INTERACTION on the Lisp side.  The strange
-  ;; calling convention is to minimise quoting at call time.
-  (while (>= (length arguments) 3)
-    (let ((index (nth 0 arguments))
-          (name (nth 1 arguments))
-          (interaction (nth 2 arguments)))
-      (fset name (pymacs-defun index interaction))
-      (setq arguments (nthcdr 3 arguments)))))
-
-(defun pymacs-defun (index interaction)
-  ;; Register INDEX on the Lisp side with a Python object that is a function,
-  ;; and return a lambda form calling that function.  If the INTERACTION
-  ;; specification is nil, the function is not interactive.  Otherwise, the
-  ;; function is interactive, INTERACTION is then either a string, or the
-  ;; index of an argument-less Python function returning the argument list.
-  (let ((object (pymacs-python index)))
-    (cond ((null interaction)
-           `(lambda (&rest arguments)
-              (pymacs-apply ',object arguments)))
-          ((stringp interaction)
-           `(lambda (&rest arguments)
-              (interactive ,interaction)
-              (pymacs-apply ',object arguments)))
-          (t `(lambda (&rest arguments)
-                (interactive (pymacs-call ',(pymacs-python interaction)))
-                (pymacs-apply ',object arguments))))))
-
-(defun pymacs-python (index)
-  ;; Register on the Lisp side a Python object having INDEX, and return it.
-  ;; The result is meant to be recognised specially by `print-for-eval', and
-  ;; in the function position by `print-for-apply'.
-  (let ((object (cons 'pymacs-python index)))
-    (when pymacs-use-hash-tables
-      (puthash index object pymacs-weak-hash)
-      (setq pymacs-used-ids (cons index pymacs-used-ids)))
-    object))
-
-;;; Generating Python code.
-
-;; Many Lisp expressions cannot fully be represented in Python, at least
-;; because the object is mutable on the Lisp side.  Such objects are allocated
-;; somewhere into a vector of handles, and the handle index is used for
-;; communication instead of the expression itself.
-
-(defvar pymacs-lisp nil
-  "Vector of handles to hold transmitted expressions.")
-
-(defvar pymacs-freed-list nil
-  "List of unallocated indices in Lisp.")
-
-;; When the Python GC is done with a Lisp object, a communication occurs so to
-;; free the object on the Lisp side as well.
-
-(defun pymacs-allocate-lisp (expression)
-  ;; This function allocates some handle for an EXPRESSION, and return its
-  ;; index.
-  (unless pymacs-freed-list
-    (let* ((previous pymacs-lisp)
-           (old-size (length previous))
-           (new-size (if (zerop old-size) 100 (+ old-size (/ old-size 2))))
-           (counter new-size))
-      (setq pymacs-lisp (make-vector new-size nil))
-      (while (> counter 0)
-        (setq counter (1- counter))
-        (if (< counter old-size)
-            (aset pymacs-lisp counter (aref previous counter))
-          (setq pymacs-freed-list (cons counter pymacs-freed-list))))))
-  (let ((index (car pymacs-freed-list)))
-    (setq pymacs-freed-list (cdr pymacs-freed-list))
-    (aset pymacs-lisp index expression)
-    index))
-
-(defun pymacs-free-lisp (indices)
-  ;; This function is triggered from Python side for Lisp handles which lost
-  ;; their last reference.  These references should be cut on the Lisp side as
-  ;; well, or else, the objects will never be garbage-collected.
-  (while indices
-    (let ((index (car indices)))
-      (aset pymacs-lisp index nil)
-      (setq pymacs-freed-list (cons index pymacs-freed-list)
-            indices (cdr indices)))))
-
-(defun pymacs-print-for-apply (function arguments)
-  ;; This function prints a Python expression calling FUNCTION, which is a
-  ;; string naming a Python function, or a Python reference, over all its
-  ;; ARGUMENTS, which are Lisp expressions.
-  (let ((separator "")
-        argument)
-    (if (eq (car-safe function) 'pymacs-python)
-        (princ (format "python[%d]" (cdr function)))
-      (princ function))
-    (princ "(")
-    (while arguments
-      (setq argument (car arguments)
-            arguments (cdr arguments))
-      (princ separator)
-      (setq separator ", ")
-      (pymacs-print-for-eval argument))
-    (princ ")")))
-
-(defun pymacs-print-for-eval (expression)
-  ;; This function prints a Python expression out of a Lisp EXPRESSION.
-  (let (done)
-    (cond ((not expression)
-           (princ "None")
-           (setq done t))
-          ((eq expression t)
-           (princ "True")
-           (setq done t))
-          ((numberp expression)
-           (princ expression)
-           (setq done t))
-          ((stringp expression)
-           (when (or pymacs-forget-mutability
-                     (not pymacs-mutable-strings))
-             (let* ((multibyte (pymacs-multibyte-string-p expression))
-                    (text (if multibyte
-                              (encode-coding-string expression 'utf-8)
-                            (copy-sequence expression))))
-               (set-text-properties 0 (length text) nil text)
-               (princ (mapconcat 'identity
-                                 (split-string (prin1-to-string text) "\n")
-                                 "\\n"))
-               (when (and multibyte
-                          (not (equal (find-charset-string text) '(ascii))))
-                 (princ ".decode('UTF-8')")))
-             (setq done t)))
-          ((symbolp expression)
-           (let ((name (symbol-name expression)))
-             ;; The symbol can only be transmitted when in the main oblist.
-             (when (eq expression (intern-soft name))
-               (princ "lisp[")
-               (prin1 name)
-               (princ "]")
-               (setq done t))))
-          ((vectorp expression)
-           (when pymacs-forget-mutability
-             (let ((limit (length expression))
-                   (counter 0))
-               (princ "(")
-               (while (< counter limit)
-                 (unless (zerop counter)
-                   (princ ", "))
-                 (pymacs-print-for-eval (aref expression counter))
-                 (setq counter (1+ counter)))
-               (when (= limit 1)
-                 (princ ","))
-               (princ ")")
-               (setq done t))))
-          ((eq (car-safe expression) 'pymacs-python)
-           (princ "python[")
-           (princ (cdr expression))
-           (princ "]")
-           (setq done t))
-          ((pymacs-proper-list-p expression)
-           (when pymacs-forget-mutability
-             (princ "[")
-             (pymacs-print-for-eval (car expression))
-             (while (setq expression (cdr expression))
-               (princ ", ")
-               (pymacs-print-for-eval (car expression)))
-             (princ "]")
-             (setq done t))))
-    (unless done
-      (let ((class (cond ((vectorp expression) "Vector")
-                         ((and pymacs-use-hash-tables
-                               (hash-table-p expression))
-                          "Table")
-                         ((bufferp expression) "Buffer")
-                         ((pymacs-proper-list-p expression) "List")
-                         (t "Lisp"))))
-        (princ class)
-        (princ "(")
-        (princ (pymacs-allocate-lisp expression))
-        (princ ")")))))
-
-;;; Communication protocol.
-
-(defvar pymacs-transit-buffer nil
-  "Communication buffer between Emacs and Python.")
-
-;; The principle behind the communication protocol is that it is easier to
-;; generate than parse, and that each language already has its own parser.
-;; So, the Emacs side generates Python text for the Python side to interpret,
-;; while the Python side generates Lisp text for the Lisp side to interpret.
-;; About nothing but expressions are transmitted, which are evaluated on
-;; arrival.  The pseudo `reply' function is meant to signal the final result
-;; of a series of exchanges following a request, while the pseudo `error'
-;; function is meant to explain why an exchange could not have been completed.
-
-;; The protocol itself is rather simple, and contains human readable text
-;; only.  A message starts at the beginning of a line in the communication
-;; buffer, either with `>' for the Lisp to Python direction, or `<' for the
-;; Python to Lisp direction.  This is followed by a decimal number giving the
-;; length of the message text, a TAB character, and the message text itself.
-;; Message direction alternates systematically between messages, it never
-;; occurs that two successive messages are sent in the same direction.  The
-;; first message is received from the Python side, it is `(version VERSION)'.
-
-(defun pymacs-start-services ()
-  ;; This function gets called automatically, as needed.
-  (let ((buffer (get-buffer-create "*Pymacs*")))
-    (with-current-buffer buffer
-      (buffer-disable-undo)
-      (set-buffer-multibyte nil)
-      (set-buffer-file-coding-system 'raw-text)
-      (save-match-data
-        ;; Launch the Pymacs helper.
-        (let ((process
-               (apply 'start-process "pymacs" buffer
-                      (let ((python (getenv "PYMACS_PYTHON")))
-                        (if (or (null python) (equal python ""))
-                            "python"
-                          python))
-                      "-c" (concat "import sys;"
-                                   " from Pymacs.pymacs import main;"
-                                   " main(*sys.argv[1:])")
-                      (mapcar 'expand-file-name pymacs-load-path))))
-          (cond ((fboundp 'set-process-query-on-exit-flag)
-                 (set-process-query-on-exit-flag process nil))
-                ((fboundp 'process-kill-without-query-process)
-                 (process-kill-without-query process)))
-          ;; Receive the synchronising reply.
-          (while (progn
-                   (goto-char (point-min))
-                   (not (re-search-forward "<\\([0-9]+\\)\t" nil t)))
-            (unless (accept-process-output process pymacs-timeout-at-start)
-              (pymacs-report-error
-               "Pymacs helper did not start within %d seconds"
-                     pymacs-timeout-at-start)))
-          (let ((marker (process-mark process))
-                (limit-position (+ (match-end 0)
-                                   (string-to-number (match-string 1)))))
-            (while (< (marker-position marker) limit-position)
-              (unless (accept-process-output process pymacs-timeout-at-start)
-                (pymacs-report-error
-                 "Pymacs helper probably was interrupted at start")))))
-        ;; Check that synchronisation occurred.
-        (goto-char (match-end 0))
-        (let ((reply (read (current-buffer))))
-          (if (and (pymacs-proper-list-p reply)
-                   (= (length reply) 2)
-                   (eq (car reply) 'version))
-              (unless (string-equal (cadr reply) "0.23")
-                (pymacs-report-error
-                 "Pymacs Lisp version is 0.23, Python is %s"
-                 (cadr reply)))
-            (pymacs-report-error "Pymacs got an invalid initial reply")))))
-    (when pymacs-use-hash-tables
-      (if pymacs-weak-hash
-          ;; A previous Pymacs session occurred in *this* Emacs session.  Some
-          ;; IDs may hang around, which do not correspond to anything on the
-          ;; Python side.  Python should not recycle such IDs for new objects.
-          (when pymacs-used-ids
-            (let ((pymacs-transit-buffer buffer)
-                  (pymacs-forget-mutability t))
-              (pymacs-apply "zombie_python" pymacs-used-ids)))
-        (setq pymacs-weak-hash (make-hash-table :weakness 'value)))
-      (if (boundp 'post-gc-hook)
-          (add-hook 'post-gc-hook 'pymacs-schedule-gc)
-        (setq pymacs-gc-timer (run-at-time 20 20 'pymacs-schedule-gc))))
-    ;; If nothing failed, only then declare that Pymacs has started!
-    (setq pymacs-transit-buffer buffer)))
-
-(defun pymacs-terminate-services ()
-  ;; This function is mainly provided for documentation purposes.
-  (interactive)
-  (garbage-collect)
-  (pymacs-garbage-collect)
-  (when (or (not pymacs-used-ids)
-            (yes-or-no-p "\
-Killing the Pymacs helper might create zombie objects.  Kill? "))
-    (cond ((boundp 'post-gc-hook)
-           (remove-hook 'post-gc-hook 'pymacs-schedule-gc))
-          ((timerp pymacs-gc-timer)
-           (cancel-timer pymacs-gc-timer)))
-    (when pymacs-transit-buffer
-      (kill-buffer pymacs-transit-buffer))
-    (setq pymacs-gc-running nil
-          pymacs-gc-timer nil
-          pymacs-transit-buffer nil
-          pymacs-lisp nil
-          pymacs-freed-list nil)))
-
-(defun pymacs-serve-until-reply (action inserter)
-  ;; This function builds a Python request by printing ACTION and
-  ;; evaluating INSERTER, which itself prints an argument.  It then
-  ;; sends the request to the Pymacs helper, and serves all
-  ;; sub-requests coming from the Python side, until either a reply or
-  ;; an error is finally received.
-  (unless (and pymacs-transit-buffer
-               (buffer-name pymacs-transit-buffer)
-               (get-buffer-process pymacs-transit-buffer))
-    (pymacs-start-services))
-  (when pymacs-gc-wanted
-    (pymacs-garbage-collect))
-  (let ((inhibit-quit t)
-        done value)
-    (while (not done)
-      (let ((form (pymacs-round-trip action inserter)))
-        (setq action (car form))
-        (when (eq action 'free)
-          (pymacs-free-lisp (cadr form))
-          (setq form (cddr form)
-                action (car form)))
-        (let* ((pair (pymacs-interruptible-eval (cadr form)))
-               (success (cdr pair)))
-          (setq value (car pair))
-          (cond ((eq action 'eval)
-                 (if success
-                     (setq action "return"
-                           inserter `(pymacs-print-for-eval ',value))
-                   (setq action "raise"
-                         inserter `(let ((pymacs-forget-mutability t))
-                                     (pymacs-print-for-eval ,value)))))
-                ((eq action 'expand)
-                 (if success
-                     (setq action "return"
-                           inserter `(let ((pymacs-forget-mutability t))
-                                       (pymacs-print-for-eval ,value)))
-                   (setq action "raise"
-                         inserter `(let ((pymacs-forget-mutability t))
-                                     (pymacs-print-for-eval ,value)))))
-                ((eq action 'return)
-                 (if success
-                     (setq done t)
-                   (pymacs-report-error "%s" value)))
-                ((eq action 'raise)
-                 (if success
-                     (pymacs-report-error "Python: %s" value)
-                   (pymacs-report-error "%s" value)))
-                (t (pymacs-report-error "Protocol error: %s" form))))))
-    value))
-
-(defun pymacs-round-trip (action inserter)
-  ;; This function produces a Python request by printing and
-  ;; evaluating INSERTER, which itself prints an argument.  It sends
-  ;; the request to the Pymacs helper, awaits for any kind of reply,
-  ;; and returns it.
-  (with-current-buffer pymacs-transit-buffer
-    ;; Possibly trim the beginning of the transit buffer.
-    (cond ((not pymacs-trace-transit)
-           (erase-buffer))
-          ((consp pymacs-trace-transit)
-           (when (> (buffer-size) (cdr pymacs-trace-transit))
-             (let ((cut (- (buffer-size) (car pymacs-trace-transit))))
-               (when (> cut 0)
-                 (save-excursion
-                   (goto-char cut)
-                   (unless (memq (preceding-char) '(0 ?\n))
-                     (forward-line 1))
-                   (delete-region (point-min) (point))))))))
-    ;; Send the request, wait for a reply, and process it.
-    (let* ((process (get-buffer-process pymacs-transit-buffer))
-           (status (process-status process))
-           (marker (process-mark process))
-           (moving (= (point) marker))
-           send-position reply-position reply)
-      (save-excursion
-        (save-match-data
-          ;; Encode request.
-          (setq send-position (marker-position marker))
-          (let ((standard-output marker))
-            (princ action)
-            (princ " ")
-            (eval inserter))
-          (goto-char marker)
-          (unless (= (preceding-char) ?\n)
-            (princ "\n" marker))
-          ;; Send request text.
-          (goto-char send-position)
-          (insert (format ">%d\t" (- marker send-position)))
-          (setq reply-position (marker-position marker))
-          (process-send-region process send-position marker)
-          ;; Receive reply text.
-          (while (and (eq status 'run)
-                      (progn
-                        (goto-char reply-position)
-                        (not (re-search-forward "<\\([0-9]+\\)\t" nil t))))
-            (unless (accept-process-output process pymacs-timeout-at-reply)
-              (setq status (process-status process))))
-          (when (eq status 'run)
-            (let ((limit-position (+ (match-end 0)
-                                     (string-to-number (match-string 1)))))
-              (while (and (eq status 'run)
-                          (< (marker-position marker) limit-position))
-                (unless (accept-process-output process pymacs-timeout-at-line)
-                  (setq status (process-status process))))))
-          ;; Decode reply.
-          (if (not (eq status 'run))
-              (pymacs-report-error "Pymacs helper status is `%S'" status)
-            (goto-char (match-end 0))
-            (setq reply (read (current-buffer))))))
-      (when (and moving (not pymacs-trace-transit))
-        (goto-char marker))
-      reply)))
-
-(defun pymacs-interruptible-eval (expression)
-  ;; This function produces a pair (VALUE . SUCCESS) for EXPRESSION.
-  ;; A cautious evaluation of EXPRESSION is attempted, and any
-  ;; error while evaluating is caught, including Emacs quit (C-g).
-  ;; Any Emacs quit also gets forward as a SIGINT to the Pymacs handler.
-  ;; With SUCCESS being true, VALUE is the expression value.
-  ;; With SUCCESS being false, VALUE is an interruption diagnostic.
-  (condition-case info
-      (cons (let ((inhibit-quit nil)) (eval expression)) t)
-    (quit (setq quit-flag t)
-          (interrupt-process pymacs-transit-buffer)
-          (cons "*Interrupted!*" nil))
-    (error (cons (prin1-to-string info) nil))))
-
-(defun pymacs-proper-list-p (expression)
-  ;; Tell if a list is proper, id est, that it is `nil' or ends with `nil'.
-  (cond ((not expression))
-        ((consp expression) (not (cdr (last expression))))))
-
-(provide 'pymacs)
--- a/.elisp/settings/10.require.el
+++ b/.elisp/settings/10.require.el
@@ -4,6 +4,32 @@
 (setq ido-enable-flex-matching t)
 (ido-mode t)
 
+(load "package")
+(package-initialize)
+
+(setq package-archives '(("durin42" . "http://home.durin42.com/elpa/")
+                         ("elpa" . "http://tromey.com/elpa/")))
+
+(defun af-bootstrap-packages ()
+  (interactive)
+  (unless package-archive-contents (package-refresh-contents))
+  (dolist (pack '(diff-mode-
+                  doctest-mode
+                  http-twiddle
+                  ipython
+                  nose
+                  ;; disabled until I don't need a modified version
+                  ;; textmate
+                  iedit
+                  ;; from elpa
+                  js2-mode
+                  paredit
+                  yaml-mode))
+    (unless (or (member pack package-activated-list)
+                (functionp pack))
+      (message "Installing %s" (symbol-name pack))
+      (package-install pack))))
+
 (require 'python-mode)
 (require 'ipython)
 (require 'show-wspace)
deleted file mode 100644
--- a/.elisp/yaml-mode.el
+++ /dev/null
@@ -1,392 +0,0 @@
-;;; yaml-mode.el --- Major mode for editing YAML files
-
-;; Copyright (C) 2006  Yoshiki Kurihara
-
-;; Author: Yoshiki Kurihara <kurihara@cpan.org>
-;;         Marshall T. Vandegrift <llasram@gmail.com>
-;; Keywords: data yaml
-;; Version: 0.0.3
-
-;; This file is not part of Emacs
-
-;; This file 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 2, or (at your option)
-;; any later version.
-
-;; This file 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; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Commentary:
-
-;; This is a major mode for editing files in the YAML data
-;; serialization format.  It was initially developed by Yoshiki
-;; Kurihara and many features were added by Marshall Vandegrift.  As
-;; YAML and Python share the fact that indentation determines
-;; structure, this mode provides indentation and indentation command
-;; behavior very similar to that of python-mode.
-
-;;; Installation:
-
-;; To install, just drop this file into a directory in your
-;; `load-path' and (optionally) byte-compile it.  To automatically
-;; handle files ending in '.yml', add something like:
-;;
-;;    (require 'yaml-mode)
-;;    (add-to-list 'auto-mode-alist '("\\.yml$" . yaml-mode))
-;;
-;; to your .emacs file.
-;;
-;; Unlike python-mode, this mode follows the Emacs convention of not
-;; binding the ENTER key to `newline-and-indent'.  To get this
-;; behavior, add the key definition to `yaml-mode-hook':
-;;
-;;    (add-hook 'yaml-mode-hook
-;;     '(lambda ()
-;;        (define-key yaml-mode-map "\C-m" 'newline-and-indent)))
-
-;;; Known Bugs:
-
-;; YAML is easy to write but complex to parse, and this mode doesn't
-;; even really try.  Indentation and highlighting will break on
-;; abnormally complicated structures.
-
-;;; Code:
-
-
-;; User definable variables
-
-(defgroup yaml nil
-  "Support for the YAML serialization format"
-  :group 'languages
-  :prefix "yaml-")
-
-(defcustom yaml-mode-hook nil
-  "*Hook run by `yaml-mode'."
-  :type 'hook
-  :group 'yaml)
-
-(defcustom yaml-indent-offset 2
-  "*Amount of offset per level of indentation."
-  :type 'integer
-  :group 'yaml)
-
-(defcustom yaml-backspace-function 'backward-delete-char-untabify
-  "*Function called by `yaml-electric-backspace' when deleting backwards."
-  :type 'function
-  :group 'yaml)
-
-(defcustom yaml-block-literal-search-lines 100
-  "*Maximum number of lines to search for start of block literals."
-  :type 'integer
-  :group 'yaml)
-
-(defcustom yaml-block-literal-electric-alist
-  '((?| . "") (?> . "-"))
-  "*Characters for which to provide electric behavior.
-The association list key should be a key code and the associated value
-should be a string containing additional characters to insert when
-that key is pressed to begin a block literal."
-  :type 'alist
-  :group 'yaml)
-
-(defface yaml-tab-face
-   '((((class color)) (:background "red" :foreground "red" :bold t))
-     (t (:reverse-video t)))
-  "Face to use for highlighting tabs in YAML files."
-  :group 'faces
-  :group 'yaml)
-
-
-;; Constants
-
-(defconst yaml-mode-version "0.0.3" "Version of `yaml-mode.'")
-
-(defconst yaml-blank-line-re "^ *$"
-  "Regexp matching a line containing only (valid) whitespace.")
-
-(defconst yaml-comment-re "\\(#*.*\\)"
-  "Regexp matching a line containing a YAML comment or delimiter.")
-
-(defconst yaml-directive-re "^\\(?:--- \\)? *%\\(\\w+\\)"
-  "Regexp matching a line contatining a YAML directive.")
-
-(defconst yaml-document-delimiter-re "^ *\\(?:---\\|[.][.][.]\\)"
-  "Rexexp matching a YAML document delimiter line.")
-
-(defconst yaml-node-anchor-alias-re "[&*]\\w+"
-  "Regexp matching a YAML node anchor or alias.")
-
-(defconst yaml-tag-re "!!?[^ \n]+"
-  "Rexexp matching a YAML tag.")
-
-(defconst yaml-bare-scalar-re
-  "\\(?:[^-:,#!\n{\\[ ]\\|[^#!\n{\\[ ]\\S-\\)[^#\n]*?"
-  "Rexexp matching a YAML bare scalar.")
-
-(defconst yaml-hash-key-re
-  (concat "\\(?:^\\(?:--- \\)?\\|{\\|\\(?:[-,] +\\)+\\) *"
-          "\\(?:" yaml-tag-re " +\\)?"
-          "\\(" yaml-bare-scalar-re "\\) *:"
-          "\\(?: +\\|$\\)")
-  "Regexp matching a single YAML hash key.")
-
-(defconst yaml-scalar-context-re
-  (concat "\\(?:^\\(?:--- \\)?\\|{\\|\\(?:[-,] +\\)+\\) *"
-          "\\(?:" yaml-bare-scalar-re " *: \\)?")
-  "Regexp indicating the begininng of a scalar context.")
-
-(defconst yaml-nested-map-re
-  (concat ".*: *\\(?:&.*\\|{ *\\|" yaml-tag-re " *\\)?$")
-  "Regexp matching a line beginning a YAML nested structure.")
-
-(defconst yaml-block-literal-base-re " *[>|][-+0-9]* *\\(?:\n\\|\\'\\)"
-  "Regexp matching the substring start of a block literal.")
-
-(defconst yaml-block-literal-re
-  (concat yaml-scalar-context-re
-          "\\(?:" yaml-tag-re "\\)?"
-          yaml-block-literal-base-re)
-  "Regexp matching a line beginning a YAML block literal")
-
-(defconst yaml-nested-sequence-re
-  (concat "^\\(?: *- +\\)+"
-          "\\(?:" yaml-bare-scalar-re " *:\\(?: +.*\\)?\\)?$")
-  "Regexp matching a line containing one or more nested YAML sequences")
-
-(defconst yaml-constant-scalars-re
-  (concat "\\(?:^\\|\\(?::\\|-\\|,\\|{\\|\\[\\) +\\) *"
-          (regexp-opt
-           '("~" "null" "Null" "NULL"
-             ".nan" ".NaN" ".NAN"
-             ".inf" ".Inf" ".INF"
-             "-.inf" "-.Inf" "-.INF"
-             "y" "Y" "yes" "Yes" "YES" "n" "N" "no" "No" "NO"
-             "true" "True" "TRUE" "false" "False" "FALSE"
-             "on" "On" "ON" "off" "Off" "OFF") t)
-          " *$")
-  "Regexp matching certain scalar constants in scalar context")
-
-
-;; Mode setup
-
-(defvar yaml-mode-map ()
-  "Keymap used in `yaml-mode' buffers.")
-(if yaml-mode-map
-    nil
-  (setq yaml-mode-map (make-sparse-keymap))
-  (define-key yaml-mode-map "|" 'yaml-electric-bar-and-angle)
-  (define-key yaml-mode-map ">" 'yaml-electric-bar-and-angle)
-  (define-key yaml-mode-map "-" 'yaml-electric-dash-and-dot)
-  (define-key yaml-mode-map "." 'yaml-electric-dash-and-dot)
-  (define-key yaml-mode-map [backspace] 'yaml-electric-backspace)
-  (define-key yaml-mode-map "\C-j" 'newline-and-indent))
-
-(defvar yaml-mode-syntax-table nil
-  "Syntax table in use in yaml-mode buffers.")
-(if yaml-mode-syntax-table
-    nil
-  (setq yaml-mode-syntax-table (make-syntax-table))
-  (modify-syntax-entry ?\' "\"" yaml-mode-syntax-table)
-  (modify-syntax-entry ?\" "\"" yaml-mode-syntax-table)
-  (modify-syntax-entry ?# "<" yaml-mode-syntax-table)
-  (modify-syntax-entry ?\n ">" yaml-mode-syntax-table)
-  (modify-syntax-entry ?\\ "\\" yaml-mode-syntax-table)
-  (modify-syntax-entry ?- "." yaml-mode-syntax-table)
-  (modify-syntax-entry ?_ "_" yaml-mode-syntax-table)
-  (modify-syntax-entry ?\( "." yaml-mode-syntax-table)
-  (modify-syntax-entry ?\) "." yaml-mode-syntax-table)
-  (modify-syntax-entry ?\{ "(}" yaml-mode-syntax-table)
-  (modify-syntax-entry ?\} "){" yaml-mode-syntax-table)
-  (modify-syntax-entry ?\[ "(]" yaml-mode-syntax-table)
-  (modify-syntax-entry ?\] ")[" yaml-mode-syntax-table))
-
-(define-derived-mode yaml-mode fundamental-mode "YAML"
-  "Simple mode to edit YAML.
-
-\\{yaml-mode-map}"
-  (set (make-local-variable 'comment-start) "# ")
-  (set (make-local-variable 'comment-start-skip) "#+ *")
-  (set (make-local-variable 'indent-line-function) 'yaml-indent-line)
-  (set (make-local-variable 'font-lock-defaults)
-       '(yaml-font-lock-keywords
-         nil nil nil nil
-         (font-lock-syntactic-keywords . yaml-font-lock-syntactic-keywords))))
-
-
-;; Font-lock support
-
-(defvar yaml-font-lock-keywords
-   (list
-    (cons yaml-comment-re '(1 font-lock-comment-face))
-    (cons yaml-constant-scalars-re '(1 font-lock-constant-face))
-    (cons yaml-tag-re '(0 font-lock-type-face))
-    (cons yaml-node-anchor-alias-re '(0 font-lock-function-name-face t))
-    (cons yaml-hash-key-re '(1 font-lock-variable-name-face t))
-    (cons yaml-document-delimiter-re '(0 font-lock-comment-face))
-    (cons yaml-directive-re '(1 font-lock-builtin-face))
-    '(yaml-font-lock-block-literals 0 font-lock-string-face t)
-    '("^[\t]+" 0 'yaml-tab-face t))
-   "Additional expressions to highlight in YAML mode.")
-
-(defvar yaml-font-lock-syntactic-keywords
-  (list '(yaml-syntactic-block-literals 0 "." t))
-  "Additional syntax features to highlight in YAML mode.")
-
-
-(defun yaml-font-lock-block-literals (bound)
-  "Find lines within block literals.
-Find the next line of the first (if any) block literal after point and
-prior to BOUND.  Returns the beginning and end of the block literal
-line in the match data, as consumed by `font-lock-keywords' matcher
-functions.  The function begins by searching backwards to determine
-whether or not the current line is within a block literal.  This could
-be time-consuming in large buffers, so the number of lines searched is
-artificially limitted to the value of
-`yaml-block-literal-search-lines'."
-  (if (eolp) (goto-char (1+ (point))))
-  (unless (or (eobp) (>= (point) bound))
-    (let ((begin (point))
-          (end (min (1+ (point-at-eol)) bound)))
-      (goto-char (point-at-bol))
-      (while (and (looking-at yaml-blank-line-re) (not (bobp)))
-        (forward-line -1))
-      (let ((nlines yaml-block-literal-search-lines) 
-            (min-level (current-indentation))) 
-      (forward-line -1) 
-      (while (and (/= nlines 0) 
-                  (/= min-level 0) 
-                  (not (looking-at yaml-block-literal-re)) 
-                  (not (bobp))) 
-        (set 'nlines (1- nlines)) 
-        (unless (looking-at yaml-blank-line-re) 
-          (set 'min-level (min min-level (current-indentation)))) 
-        (forward-line -1)) 
-      (cond
-       ((and (< (current-indentation) min-level)
-             (looking-at yaml-block-literal-re))
-          (goto-char end) (set-match-data (list begin end)) t)
-         ((progn 
-            (goto-char begin)
-            (re-search-forward (concat yaml-block-literal-re
-                                       " *\\(.*\\)\n")
-                               bound t))
-          (set-match-data (nthcdr 2 (match-data))) t))))))
-
-(defun yaml-syntactic-block-literals (bound)
-  "Find quote characters within block literals.
-Finds the first quote character within a block literal (if any) after
-point and prior to BOUND.  Returns the position of the quote character
-in the match data, as consumed by matcher functions in
-`font-lock-syntactic-keywords'.  This allows the mode to treat ['\"]
-characters in block literals as punctuation syntax instead of string
-syntax, preventing unmatched quotes in block literals from painting
-the entire buffer in `font-lock-string-face'."
-  (let ((found nil))
-    (while (and (not found)
-                (/= (point) bound)
-                (yaml-font-lock-block-literals bound))
-      (let ((begin (match-beginning 0)) (end (match-end 0)))
-        (goto-char begin)
-        (cond
-         ((re-search-forward "['\"]" end t) (setq found t))
-         ((goto-char end)))))
-    found))
-
-
-;; Indentation and electric keys
-
-(defun yaml-compute-indentation ()
-  "Calculate the maximum sensible indentation for the current line."
-  (save-excursion
-    (beginning-of-line)
-    (if (looking-at yaml-document-delimiter-re) 0
-      (forward-line -1)
-      (while (and (looking-at yaml-blank-line-re)
-                  (> (point) (point-min)))
-        (forward-line -1))
-      (+ (current-indentation)
-         (if (looking-at yaml-nested-map-re) yaml-indent-offset 0)
-         (if (looking-at yaml-nested-sequence-re) yaml-indent-offset 0)
-         (if (looking-at yaml-block-literal-re) yaml-indent-offset 0)))))
-
-(defun yaml-indent-line ()
-  "Indent the current line.
-The first time this command is used, the line will be indented to the
-maximum sensible indentation.  Each immediately subsequent usage will
-back-dent the line by `yaml-indent-offset' spaces.  On reaching column
-0, it will cycle back to the maximum sensible indentation."
-  (interactive "*")
-  (let ((ci (current-indentation))
-        (cc (current-column))
-        (need (yaml-compute-indentation)))
-    (save-excursion
-      (beginning-of-line)
-      (delete-horizontal-space)
-      (if (and (equal last-command this-command) (/= ci 0))
-          (indent-to (* (/ (- ci 1) yaml-indent-offset) yaml-indent-offset))
-        (indent-to need)))
-      (if (< (current-column) (current-indentation))
-          (forward-to-indentation 0))))
-
-(defun yaml-electric-backspace (arg)
-  "Delete characters or back-dent the current line.
-If invoked following only whitespace on a line, will back-dent to the
-immediately previous multiple of `yaml-indent-offset' spaces."
-  (interactive "*p")
-  (if (or (/= (current-indentation) (current-column)) (bolp))
-      (funcall yaml-backspace-function arg)
-    (let ((ci (current-column)))
-      (beginning-of-line)
-      (delete-horizontal-space)
-      (indent-to (* (/ (- ci (* arg yaml-indent-offset))
-                       yaml-indent-offset)
-                    yaml-indent-offset)))))
-  
-(defun yaml-electric-bar-and-angle (arg)
-  "Insert the bound key and possibly begin a block literal.
-Inserts the bound key.  If inserting the bound key causes the current
-line to match the initial line of a block literal, then inserts the
-matching string from `yaml-block-literal-electric-alist', a newline,
-and indents appropriately."
-  (interactive "*P")
-  (self-insert-command (prefix-numeric-value arg))
-  (let ((extra-chars
-         (assoc last-command-char
-                yaml-block-literal-electric-alist)))
-    (cond
-     ((and extra-chars (not arg) (eolp)
-           (save-excursion
-             (beginning-of-line)
-             (looking-at yaml-block-literal-re)))
-      (insert (cdr extra-chars))
-      (newline-and-indent)))))
-
-(defun yaml-electric-dash-and-dot (arg)
-  "Insert the bound key and possibly de-dent line.
-Inserts the bound key.  If inserting the bound key causes the current
-line to match a document delimiter, de-dent the line to the left
-margin."
-  (interactive "*P")
-  (self-insert-command (prefix-numeric-value arg))
-  (save-excursion
-    (beginning-of-line)
-    (if (and (not arg) (looking-at yaml-document-delimiter-re))
-        (delete-horizontal-space))))
-
-(defun yaml-mode-version ()
-  "Diplay version of `yaml-mode'."
-  (interactive)
-  (message "yaml-mode %s" yaml-mode-version)
-  yaml-mode-version)
-
-(provide 'yaml-mode)
-
-;;; yaml-mode.el ends here