Full Code of lantiga/ki for AI

master 5c2fdfc5f0ad cached
38 files
1.4 MB
397.5k tokens
1317 symbols
1 requests
Download .txt
Showing preview only (1,509K chars total). Download the full file or copy to clipboard to get everything.
Repository: lantiga/ki
Branch: master
Commit: 5c2fdfc5f0ad
Files: 38
Total size: 1.4 MB

Directory structure:
gitextract_5ucek8is/

├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── bin/
│   └── ki
├── editor/
│   ├── addon/
│   │   └── runmode.js
│   ├── codemirror.css
│   ├── editor.html
│   ├── index.html
│   ├── mode/
│   │   ├── javascript/
│   │   │   └── javascript.js
│   │   └── runmode.js
│   ├── scripts/
│   │   ├── codemirror.js
│   │   ├── editor.js
│   │   ├── escodegen.js
│   │   ├── escope.js
│   │   ├── estraverse.js
│   │   ├── expander.js
│   │   ├── jquery.js
│   │   ├── ki.js
│   │   ├── ki.sjs
│   │   ├── main.js
│   │   ├── mori.js
│   │   ├── parser.js
│   │   ├── patterns.js
│   │   ├── require.js
│   │   ├── scopedEval.js
│   │   ├── stxcase.js
│   │   ├── sweet.js
│   │   ├── syntax.js
│   │   ├── text.js
│   │   └── underscore.js
│   └── theme/
│       └── sweetprism.css
├── lib/
│   ├── ki.js
│   └── ki_run.js
├── macros/
│   └── index.js
├── package.json
├── src/
│   └── ki.sjs
└── test/
    └── core.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.DS_Store

node_modules
npm-debug.log

/test/core.out.js


================================================
FILE: Gruntfile.js
================================================
module.exports = function(grunt) {
  grunt.initConfig({
    mochaTest: {
      test: {
        options: {
          reporter: 'spec'
        },
        src: 'test/**/*.out.js'
      }
    }
  });

  grunt.registerTask('build', function() {
    //var macro = '';
    //var files = ['ki.sjs','react.sjs','core.sjs'];
    //files.forEach(function(f) { macro += grunt.file.read('./src/' + f) + '\n'; });
    // TODO: add filenames of macro files as arguments
    var macro = grunt.file.read('./src/ki.sjs');
    grunt.file.write('./macros/index.js', macro);
    grunt.file.write('./editor/scripts/ki.sjs', macro);
    var lib = grunt.file.read('./lib/ki.js');
    grunt.file.write('./editor/scripts/ki.js', lib);
  });

  grunt.registerTask('build-test', function() {
    var path = require('path');
    var files = ['./test/core.js'];
    files.forEach(function(f) {
      grunt.file.write(f.replace('.js', '.out.js'), compileFile(f, true));
    });
  });

  //grunt.registerTask('compile', function(fileName) {
  //  console.log(this.data);
  //  grunt.log.write(compileFile(fileName));
  //});

  var moduleCtx;

  function compileFile(fileName, isTest) {
    var macro = grunt.file.read('./macros/index.js');
    var file  = grunt.file.read(fileName);
    var sweet = require('sweet.js');

    if (!moduleCtx) moduleCtx = sweet.loadModule(macro);

    return sweet.compile(file, {
      modules: [moduleCtx]
    }).code;
  }

  var parseMacros = function(code) {
    var re = /ki *macro/
    
    var current = code;
    var start = current.search(re);
    var ret;
    var macros = [];
    while (start != -1) {
      current = current.substr(start);
      ret = getNSExprs(current,2);
      macros.push(ret.matches);
      current = current.substr(ret.end);
      start = current.search(re);
    }
    
    var rules = macros.map(function(macro) { 
      return 'rule { ' + macro[0] + ' } => { _sexpr ' + macro[1] + ' }' 
    });

    return rules.join('\n');
  }

  grunt.registerTask('compile', function() {
  
    var path = require('path');
    var sweet = require('sweet.js');
    var uglify = require('uglify-js');

    var infile    = grunt.option('in');
    var outfile   = grunt.option('out');
    var sourcemap = grunt.option('sourcemap') || false;
    var minify    = grunt.option('minify') || false;
    var compress  = grunt.option('compress') || false;
  
    var file;
    if (infile) {
      file = grunt.file.read(infile);
    } 
    else if (argv._.length === 0) {
      console.log(require("optimist").help());
      return;
    }
  
    var ki_core = grunt.file.read('./macros/index.js');    

    var include = grunt.option('include');
    var includes = typeof include === 'string' ? [include] : include;
    var includeFiles = (includes || []).map(function(path) {
      return grunt.file.read(path);
    });
  
    var rules = includeFiles.map(function(includeFile) {
      return parseMacros(includeFile);
    });
    rules.push(parseMacros(file));
  
    var module = ki_core.replace('/*__macros__*/',rules.join('\n'));
  
    var options = {
      filename: infile,
      modules: [sweet.loadModule(module)]
    };
  
    var compile = function(file) {
      var file = includeFiles.join('\n') + file;
      if (sourcemap && outfile) {
        options.sourceMap = true;
        var result = sweet.compile(file, options);
        var mapfile = path.basename(outfile) + '.map';
        var code = result.code + '\n//# sourceMappingURL=' + mapfile;
        var sourceMap = result.sourceMap;
        var mapfile = outfile + '.map';
        var tmpfile = outfile + '.tmp';
        if (minify) {
          grunt.file.write(tmpfile, sourceMap);
          result = uglify.minify(code, {
            fromString: true,
            inSourceMap: tmpfile,
            outSourceMap: mapfile,
            compress: compress
          });
          code = result.code;
          sourceMap = result.map;
          grunt.file.delete(tmpfile);
        }
        grunt.file.write(outfile, code);
        grunt.file.write(mapfile, sourceMap);
      }
      else if (outfile) {
        var code = sweet.compile(file, options).code;
        if (minify) {
          code = uglify.minify(code, {fromString: true, compress: compress}).code;
        }
        grunt.file.write(outfile, code);
      }
      else {
        var code = sweet.compile(file, options).code;
        if (minify) {
          code = uglify.minify(code, {fromString: true, compress: compress}).code;
        }
        console.log(code);
      }
    }
  
    try {
      compile(file);
    }
    catch (e) {
      console.log(e);
    }
  });

  grunt.registerTask('default', ['build']);
  grunt.registerTask('test', ['build', 'build-test', 'mochaTest']);
  grunt.loadNpmTasks('grunt-mocha-test');
};




================================================
FILE: LICENSE
================================================
Copyright (C) 2014 Luca Antiga http://lantiga.github.io

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================

# ki

**lisp + mori, sweet.js**

![ki](http://ki-lang.org/images/ki-color.svg)

See [ki-lang.org](http://ki-lang.org) for more information or [try ki](http://ki-lang.org/editor/editor.html) straight in your browser.

ki is a lisp with Clojure data structures and semantics that can be intermixed with Javascript code at any level.

ki is a thin macro layer on top of [mori](https://github.com/swannodette/mori) plus a few constructs.

ki is in flux, feel free to test it out but expect glitches.


## Currently available functions / special forms

All of [mori](https://github.com/swannodette/mori).

The following list of functions / special forms
```
[] {} [$ ] {$ } add and apply atom bind catch chain cond def defmethod defmulti 
defn deref div do doto eq falsey finally fn fnth geq gt if ifNot js leq letc 
let lt loop mod mul neq nil not ns or prn recur reset str sub swap threadf 
threadl truthy try use when whenNot while 
```

Plus destructuring and source maps.

Take a look at the [tests](https://github.com/lantiga/ki/blob/master/test/core.js) to keep up with the latest additions.

## Examples

Require ki (this in turns expands into an appropriate require for mori)
```
ki require core
```

Mori's persistent data structures and Clojure(Script)-like api at your fingertips
```js
var foo = ki (vector 1 2 3)
ki (conj foo 4)
// => [1 2 3 4]
```

Plus lambdas
```js
ki (map (fn [a] (inc a)) (range 5))
// => (1 2 3 4 5)
```

Interoperability: write js in a ki form
```js
var fn1 = ki (js function (a,b) { return a + b + 2; })
```
at any level - e.g. you can use infix where it makes sense
```js
var fn2 = ki (fn [a b] (js a + b + 2))
```

and you can use ki wherever in js code
```js
function somefunc (a) {
  ki (toJs (filter (fn [el] (isEven el)) (range a))).forEach(function(el) {
      console.log(el);
      });
  return [0, 1, 2, 3, 4].filter(ki (fn [el] (isEven el)));
}
console.log(somefunc(5));
// => 0 
// => 2 
// => 4 
// [0 2 4]
```

Like a pro
```js
ki (take 6 (map (fn [x] (js x * 2)) (range 1000)))
// => (0 2 4 6 8 10)
```


## Get it

    $ npm install -g ki

All set. Now to compile a JavaScript file containing ki code into a plain JavaScript file do

    $ ki -o foo_build.js foo.js

To watch the file and have it automatically compiled whenever the file changes on disk

    $ ki -w -o foo_build.js foo.js


## License

MIT license http://www.opensource.org/licenses/mit-license.php/

Copyright (C) 2014-2015 Luca Antiga http://lantiga.github.io




================================================
FILE: bin/ki
================================================
#!/usr/bin/env node

var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)),'../lib');

var ret = require(lib + '/ki_run').run();

if (ret != -1) {
  process.exit(ret);
}



================================================
FILE: editor/addon/runmode.js
================================================
CodeMirror.runMode = function(string, modespec, callback, options) {
  var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);

  if (callback.nodeType == 1) {
    var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
    var node = callback, col = 0;
    node.innerHTML = "";
    callback = function(text, style) {
      if (text == "\n") {
        node.appendChild(document.createElement("br"));
        col = 0;
        return;
      }
      var content = "";
      // replace tabs
      for (var pos = 0;;) {
        var idx = text.indexOf("\t", pos);
        if (idx == -1) {
          content += text.slice(pos);
          col += text.length - pos;
          break;
        } else {
          col += idx - pos;
          content += text.slice(pos, idx);
          var size = tabSize - col % tabSize;
          col += size;
          for (var i = 0; i < size; ++i) content += " ";
          pos = idx + 1;
        }
      }

      if (style) {
        var sp = node.appendChild(document.createElement("span"));
        sp.className = "cm-" + style.replace(/ +/g, " cm-");
        sp.appendChild(document.createTextNode(content));
      } else {
        node.appendChild(document.createTextNode(content));
      }
    };
  }

  var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
  for (var i = 0, e = lines.length; i < e; ++i) {
    if (i) callback("\n");
    var stream = new CodeMirror.StringStream(lines[i]);
    while (!stream.eol()) {
      var style = mode.token(stream, state);
      callback(stream.current(), style, i, stream.start);
      stream.start = stream.pos;
    }
  }
};


================================================
FILE: editor/codemirror.css
================================================
/* BASICS */

.CodeMirror {
  /* Set height, width, borders, and global font properties here */
  font-family: monospace;
  height: 300px;
}
.CodeMirror-scroll {
  /* Set scrolling behaviour here */
  overflow: auto;
}

/* PADDING */

.CodeMirror-lines {
  padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
  padding: 0 4px; /* Horizontal padding of content */
}

.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
  background-color: white; /* The little square between H and V scrollbars */
}

/* GUTTER */

.CodeMirror-gutters {
  border-right: 1px solid #ddd;
  background-color: #f7f7f7;
  white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
  padding: 0 3px 0 5px;
  min-width: 20px;
  text-align: right;
  color: #999;
}

/* CURSOR */

.CodeMirror div.CodeMirror-cursor {
  border-left: 1px solid black;
  z-index: 3;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
  border-left: 1px solid silver;
}
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
  width: auto;
  border: 0;
  background: #7e7;
  z-index: 1;
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}

.cm-tab { display: inline-block; }

/* DEFAULT THEME */

.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable {color: black;}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-property {color: black;}
.cm-s-default .cm-operator {color: black;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-error {color: #f00;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}

.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}

.cm-invalidchar {color: #f00;}

div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}

/* STOP */

/* The rest of this file contains styles related to the mechanics of
   the editor. You probably shouldn't touch them. */

.CodeMirror {
  line-height: 1;
  position: relative;
  overflow: hidden;
  background: white;
  color: black;
}

.CodeMirror-scroll {
  /* 30px is the magic margin used to hide the element's real scrollbars */
  /* See overflow: hidden in .CodeMirror */
  margin-bottom: -30px; margin-right: -30px;
  padding-bottom: 30px; padding-right: 30px;
  height: 100%;
  outline: none; /* Prevent dragging from highlighting the element */
  position: relative;
}
.CodeMirror-sizer {
  position: relative;
}

/* The fake, visible scrollbars. Used to force redraw during scrolling
   before actuall scrolling happens, thus preventing shaking and
   flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
  position: absolute;
  z-index: 6;
  display: none;
}
.CodeMirror-vscrollbar {
  right: 0; top: 0;
  overflow-x: hidden;
  overflow-y: scroll;
}
.CodeMirror-hscrollbar {
  bottom: 0; left: 0;
  overflow-y: hidden;
  overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
  right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
  left: 0; bottom: 0;
}

.CodeMirror-gutters {
  position: absolute; left: 0; top: 0;
  padding-bottom: 30px;
  z-index: 3;
}
.CodeMirror-gutter {
  white-space: normal;
  height: 100%;
  padding-bottom: 30px;
  margin-bottom: -32px;
  display: inline-block;
  /* Hack to make IE7 behave */
  *zoom:1;
  *display:inline;
}
.CodeMirror-gutter-elt {
  position: absolute;
  cursor: default;
  z-index: 4;
}

.CodeMirror-lines {
  cursor: text;
}
.CodeMirror pre {
  /* Reset some styles that the rest of the page might have set */
  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
  border-width: 0;
  background: transparent;
  font-family: inherit;
  font-size: inherit;
  margin: 0;
  white-space: pre;
  word-wrap: normal;
  line-height: inherit;
  color: inherit;
  z-index: 2;
  position: relative;
  overflow: visible;
}
.CodeMirror-wrap pre {
  word-wrap: break-word;
  white-space: pre-wrap;
  word-break: normal;
}
.CodeMirror-linebackground {
  position: absolute;
  left: 0; right: 0; top: 0; bottom: 0;
  z-index: 0;
}

.CodeMirror-linewidget {
  position: relative;
  z-index: 2;
  overflow: auto;
}

.CodeMirror-widget {
}

.CodeMirror-wrap .CodeMirror-scroll {
  overflow-x: hidden;
}

.CodeMirror-measure {
  position: absolute;
  width: 100%; height: 0px;
  overflow: hidden;
  visibility: hidden;
}
.CodeMirror-measure pre { position: static; }

.CodeMirror div.CodeMirror-cursor {
  position: absolute;
  visibility: hidden;
  border-right: none;
  width: 0;
}
.CodeMirror-focused div.CodeMirror-cursor {
  visibility: visible;
}

.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }

.cm-searching {
  background: #ffa;
  background: rgba(255, 255, 0, .4);
}

/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }

@media print {
  /* Hide the cursor when printing */
  .CodeMirror div.CodeMirror-cursor {
    visibility: hidden;
  }
}


================================================
FILE: editor/editor.html
================================================
<html>
<head>
  <meta charset="utf-8">
  <title>Try ki</title>
  <script src="scripts/jquery.js"></script>
  <script src="scripts/codemirror.js"></script>
  <link rel="stylesheet" href="codemirror.css">
  <link rel="stylesheet" href="theme/sweetprism.css">
  <script src="mode/javascript/javascript.js"></script>
  
  <link href='http://fonts.googleapis.com/css?family=Droid+Sans+Mono|Open+Sans:400italic,400' rel='stylesheet' type='text/css'>
  <link href='http://fonts.googleapis.com/css?family=Lato:100' rel='stylesheet' type='text/css'>
  <script data-main="scripts/editor" src="scripts/require.js"></script>

 <style type="text/css">
 body {
  font-family: Droid Sans, Arial, sans-serif;
  line-height: 1.5;
  /*max-width: 64.3em;*/
  }
  .CodeMirror {
    font-size: 14px;
    height: 100%;
  }

  #options {
    position: absolute;
    font-size: 14px;
    font-family: Droid Sans, Arial, sans-serif;
    line-height: 1.5;
    top: 10px;
    right: 40px;
    z-index: 1;
  }

  #header {
    position: absolute;
    top: 0;
    right: 50%;
    bottom: 0;
    left: 0;

    font-size: 150%;
    color: rgb(68, 68, 68);
    font-family: 'Droid Sans Mono',Helvetica Neue,Helvetica,Arial,sans-serif;
    font-weight: 100;
    padding-left: 20px;
  }

  #controls {
    position: absolute;;
    top: 5;
    right: 0;
    bottom: 0;
    left: 50%;
  }

  #return {
    color: blue;
    position: absolute;
    background-color: white;
    /*right: 10;*/
    z-index: 10;
    bottom: 10;
    /*left: 50%;*/
    /*padding-top: 20px;*/
    /*padding-left: 55px;*/
    padding: 10px;
  }

  #errors {
    color: red;
    position: absolute;
    background-color: white;
    /*right: 10;*/
    z-index: 10;
    bottom: 10;
    /*left: 50%;*/
    /*padding-top: 20px;*/
    /*padding-left: 55px;*/
    padding: 10px;
  }

  #edit-box {
    position: absolute;
    top: 30px;
    right: 50%;
    bottom: 0;
    left: 0;
  }

  #output-box {
    position: absolute;
    top: 30px;
    right: 0;
    bottom: 0;
    left: 50%;
  }

  </style>
</head>
<body>

  <div id='header'>
     Try ki: a lisp for your JavaScript
  </div>
  
  <div id="controls">
    <input id="btn-reload-macros" type="button" value="Reload macros" />
    <input id="btn-run" type="button" value="Run (Ctrl+Enter)" />
    <input id="ck-require" type="checkbox" value="require" />Display require expansion
  </div>

  <pre id="errors">
  </pre>
 
  <pre id="return">
  </pre>
  
  <div id='edit-box' style='visibility: hidden;'>
    <textarea id="editor">/*
Welcome to ki! 

Here's some code to get you started
*/

ki require core

var r = ki (range 1 10);

return r;
    
    </textarea>
  </div>
  
  <div id='output-box' style='visibility: hidden;'>
    <textarea id="output"></textarea>
  </div>

</body>
</html>


================================================
FILE: editor/index.html
================================================
<html>
  <head>
    <script data-main="scripts/main" src="scripts/require.js"></script>
  </head>
  <body>
  </body>
</html>


================================================
FILE: editor/mode/javascript/javascript.js
================================================
// TODO actually recognize syntax of TypeScript constructs

CodeMirror.defineMode("javascript", function(config, parserConfig) {
  var indentUnit = config.indentUnit;
  var jsonMode = parserConfig.json;
  var isTS = parserConfig.typescript;

  // Tokenizer

  var keywords = function(){
    function kw(type) {return {type: type, style: "keyword"};}
    var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
    var operator = kw("operator"), atom = {type: "atom", style: "atom"};
    
    var jsKeywords = {
      "if": A, "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
      "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
      "var": kw("var"), "const": kw("var"), "let": kw("var"),
      "function": kw("function"), "catch": kw("catch"),
      "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
      "in": operator, "typeof": operator, "instanceof": operator,
      "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom
    };

    // Extend the 'normal' keywords with the TypeScript language extensions
    if (isTS) {
      var type = {type: "variable", style: "variable-3"};
      var tsKeywords = {
        // object-like things
        "interface": kw("interface"),
        "class": kw("class"),
        "extends": kw("extends"),
        "constructor": kw("constructor"),

        // scope modifiers
        "public": kw("public"),
        "private": kw("private"),
        "protected": kw("protected"),
        "static": kw("static"),

        "super": kw("super"),

        // types
        "string": type, "number": type, "bool": type, "any": type
      };

      for (var attr in tsKeywords) {
        jsKeywords[attr] = tsKeywords[attr];
      }
    }

    return jsKeywords;
  }();

  var isOperatorChar = /[+\-*&%=<>!?|]/;

  function chain(stream, state, f) {
    state.tokenize = f;
    return f(stream, state);
  }

  function nextUntilUnescaped(stream, end) {
    var escaped = false, next;
    while ((next = stream.next()) != null) {
      if (next == end && !escaped)
        return false;
      escaped = !escaped && next == "\\";
    }
    return escaped;
  }

  // Used as scratch variables to communicate multiple values without
  // consing up tons of objects.
  var type, content;
  function ret(tp, style, cont) {
    type = tp; content = cont;
    return style;
  }

  function jsTokenBase(stream, state) {
    var ch = stream.next();
    if (ch == '"' || ch == "'")
      return chain(stream, state, jsTokenString(ch));
    else if (/[\[\]{}\(\),;\:\.]/.test(ch))
      return ret(ch);
    else if (ch == "0" && stream.eat(/x/i)) {
      stream.eatWhile(/[\da-f]/i);
      return ret("number", "number");
    }      
    else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
      stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
      return ret("number", "number");
    }
    else if (ch == "/") {
      if (stream.eat("*")) {
        return chain(stream, state, jsTokenComment);
      }
      else if (stream.eat("/")) {
        stream.skipToEnd();
        return ret("comment", "comment");
      }
      else if (state.lastType == "operator" || state.lastType == "keyword c" ||
               /^[\[{}\(,;:]$/.test(state.lastType)) {
        nextUntilUnescaped(stream, "/");
        stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
        return ret("regexp", "string-2");
      }
      else {
        stream.eatWhile(isOperatorChar);
        return ret("operator", null, stream.current());
      }
    }
    else if (ch == "#") {
        stream.skipToEnd();
        return ret("error", "error");
    }
    else if (isOperatorChar.test(ch)) {
      stream.eatWhile(isOperatorChar);
      return ret("operator", null, stream.current());
    }
    else {
      stream.eatWhile(/[\w\$_]/);
      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
      return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
                     ret("variable", "variable", word);
    }
  }

  function jsTokenString(quote) {
    return function(stream, state) {
      if (!nextUntilUnescaped(stream, quote))
        state.tokenize = jsTokenBase;
      return ret("string", "string");
    };
  }

  function jsTokenComment(stream, state) {
    var maybeEnd = false, ch;
    while (ch = stream.next()) {
      if (ch == "/" && maybeEnd) {
        state.tokenize = jsTokenBase;
        break;
      }
      maybeEnd = (ch == "*");
    }
    return ret("comment", "comment");
  }

  // Parser

  var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true};

  function JSLexical(indented, column, type, align, prev, info) {
    this.indented = indented;
    this.column = column;
    this.type = type;
    this.prev = prev;
    this.info = info;
    if (align != null) this.align = align;
  }

  function inScope(state, varname) {
    for (var v = state.localVars; v; v = v.next)
      if (v.name == varname) return true;
  }

  function parseJS(state, style, type, content, stream) {
    var cc = state.cc;
    // Communicate our context to the combinators.
    // (Less wasteful than consing up a hundred closures on every call.)
    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
  
    if (!state.lexical.hasOwnProperty("align"))
      state.lexical.align = true;

    while(true) {
      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
      if (combinator(type, content)) {
        while(cc.length && cc[cc.length - 1].lex)
          cc.pop()();
        if (cx.marked) return cx.marked;
        if (type == "variable" && inScope(state, content)) return "variable-2";
        return style;
      }
    }
  }

  // Combinator utils

  var cx = {state: null, column: null, marked: null, cc: null};
  function pass() {
    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
  }
  function cont() {
    pass.apply(null, arguments);
    return true;
  }
  function register(varname) {
    var state = cx.state;
    if (state.context) {
      cx.marked = "def";
      for (var v = state.localVars; v; v = v.next)
        if (v.name == varname) return;
      state.localVars = {name: varname, next: state.localVars};
    }
  }

  // Combinators

  var defaultVars = {name: "this", next: {name: "arguments"}};
  function pushcontext() {
    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
    cx.state.localVars = defaultVars;
  }
  function popcontext() {
    cx.state.localVars = cx.state.context.vars;
    cx.state.context = cx.state.context.prev;
  }
  function pushlex(type, info) {
    var result = function() {
      var state = cx.state;
      state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info);
    };
    result.lex = true;
    return result;
  }
  function poplex() {
    var state = cx.state;
    if (state.lexical.prev) {
      if (state.lexical.type == ")")
        state.indented = state.lexical.indented;
      state.lexical = state.lexical.prev;
    }
  }
  poplex.lex = true;

  function expect(wanted) {
    return function expecting(type) {
      if (type == wanted) return cont();
      else if (wanted == ";") return pass();
      else return cont(arguments.callee);
    };
  }

  function statement(type) {
    if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
    if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
    if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
    if (type == "{") return cont(pushlex("}"), block, poplex);
    if (type == ";") return cont();
    if (type == "function") return cont(functiondef);
    if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
                                      poplex, statement, poplex);
    if (type == "variable") return cont(pushlex("stat"), maybelabel);
    if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
                                         block, poplex, poplex);
    if (type == "case") return cont(expression, expect(":"));
    if (type == "default") return cont(expect(":"));
    if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
                                        statement, poplex, popcontext);
    return pass(pushlex("stat"), expression, expect(";"), poplex);
  }
  function expression(type) {
    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
    if (type == "function") return cont(functiondef);
    if (type == "keyword c") return cont(maybeexpression);
    if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
    if (type == "operator") return cont(expression);
    if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
    if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
    return cont();
  }
  function maybeexpression(type) {
    if (type.match(/[;\}\)\],]/)) return pass();
    return pass(expression);
  }
    
  function maybeoperator(type, value) {
    if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
    if (type == "operator" && value == "?") return cont(expression, expect(":"), expression);
    if (type == ";") return;
    if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
    if (type == ".") return cont(property, maybeoperator);
    if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
  }
  function maybelabel(type) {
    if (type == ":") return cont(poplex, statement);
    return pass(maybeoperator, expect(";"), poplex);
  }
  function property(type) {
    if (type == "variable") {cx.marked = "property"; return cont();}
  }
  function objprop(type) {
    if (type == "variable") cx.marked = "property";
    if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
  }
  function commasep(what, end) {
    function proceed(type) {
      if (type == ",") return cont(what, proceed);
      if (type == end) return cont();
      return cont(expect(end));
    }
    return function commaSeparated(type) {
      if (type == end) return cont();
      else return pass(what, proceed);
    };
  }
  function block(type) {
    if (type == "}") return cont();
    return pass(statement, block);
  }
  function maybetype(type) {
    if (type == ":") return cont(typedef);
    return pass();
  }
  function typedef(type) {
    if (type == "variable"){cx.marked = "variable-3"; return cont();}
    return pass();
  }
  function vardef1(type, value) {
    if (type == "variable") {
      register(value);
      return isTS ? cont(maybetype, vardef2) : cont(vardef2);
    }
    return pass();
  }
  function vardef2(type, value) {
    if (value == "=") return cont(expression, vardef2);
    if (type == ",") return cont(vardef1);
  }
  function forspec1(type) {
    if (type == "var") return cont(vardef1, expect(";"), forspec2);
    if (type == ";") return cont(forspec2);
    if (type == "variable") return cont(formaybein);
    return cont(forspec2);
  }
  function formaybein(_type, value) {
    if (value == "in") return cont(expression);
    return cont(maybeoperator, forspec2);
  }
  function forspec2(type, value) {
    if (type == ";") return cont(forspec3);
    if (value == "in") return cont(expression);
    return cont(expression, expect(";"), forspec3);
  }
  function forspec3(type) {
    if (type != ")") cont(expression);
  }
  function functiondef(type, value) {
    if (type == "variable") {register(value); return cont(functiondef);}
    if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
  }
  function funarg(type, value) {
    if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();}
  }

  // Interface

  return {
    startState: function(basecolumn) {
      return {
        tokenize: jsTokenBase,
        lastType: null,
        cc: [],
        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
        localVars: parserConfig.localVars,
        context: parserConfig.localVars && {vars: parserConfig.localVars},
        indented: 0
      };
    },

    token: function(stream, state) {
      if (stream.sol()) {
        if (!state.lexical.hasOwnProperty("align"))
          state.lexical.align = false;
        state.indented = stream.indentation();
      }
      if (stream.eatSpace()) return null;
      var style = state.tokenize(stream, state);
      if (type == "comment") return style;
      state.lastType = type;
      return parseJS(state, style, type, content, stream);
    },

    indent: function(state, textAfter) {
      if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
      if (state.tokenize != jsTokenBase) return 0;
      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
      if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
      var type = lexical.type, closing = firstChar == type;
      if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0);
      else if (type == "form" && firstChar == "{") return lexical.indented;
      else if (type == "form") return lexical.indented + indentUnit;
      else if (type == "stat")
        return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? indentUnit : 0);
      else if (lexical.info == "switch" && !closing)
        return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
      else if (lexical.align) return lexical.column + (closing ? 0 : 1);
      else return lexical.indented + (closing ? 0 : indentUnit);
    },

    electricChars: ":{}",

    jsonMode: jsonMode
  };
});

CodeMirror.defineMIME("text/javascript", "javascript");
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });


================================================
FILE: editor/mode/runmode.js
================================================
CodeMirror.runMode = function(string, modespec, callback, options) {
  var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);

  if (callback.nodeType == 1) {
    var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
    var node = callback, col = 0;
    node.innerHTML = "";
    callback = function(text, style) {
      if (text == "\n") {
        node.appendChild(document.createElement("br"));
        col = 0;
        return;
      }
      var content = "";
      // replace tabs
      for (var pos = 0;;) {
        var idx = text.indexOf("\t", pos);
        if (idx == -1) {
          content += text.slice(pos);
          col += text.length - pos;
          break;
        } else {
          col += idx - pos;
          content += text.slice(pos, idx);
          var size = tabSize - col % tabSize;
          col += size;
          for (var i = 0; i < size; ++i) content += " ";
          pos = idx + 1;
        }
      }

      if (style) {
        var sp = node.appendChild(document.createElement("span"));
        sp.className = "cm-" + style.replace(/ +/g, " cm-");
        sp.appendChild(document.createTextNode(content));
      } else {
        node.appendChild(document.createTextNode(content));
      }
    };
  }

  var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
  for (var i = 0, e = lines.length; i < e; ++i) {
    if (i) callback("\n");
    var stream = new CodeMirror.StringStream(lines[i]);
    while (!stream.eol()) {
      var style = mode.token(stream, state);
      callback(stream.current(), style, i, stream.start);
      stream.start = stream.pos;
    }
  }
};


================================================
FILE: editor/scripts/codemirror.js
================================================
// CodeMirror version 3.14
//
// CodeMirror is the only global var we claim
window.CodeMirror = (function() {
  "use strict";

  // BROWSER SNIFFING

  // Crude, but necessary to handle a number of hard-to-feature-detect
  // bugs and behavior differences.
  var gecko = /gecko\/\d/i.test(navigator.userAgent);
  var ie = /MSIE \d/.test(navigator.userAgent);
  var ie_lt8 = ie && (document.documentMode == null || document.documentMode < 8);
  var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
  var webkit = /WebKit\//.test(navigator.userAgent);
  var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
  var chrome = /Chrome\//.test(navigator.userAgent);
  var opera = /Opera\//.test(navigator.userAgent);
  var safari = /Apple Computer/.test(navigator.vendor);
  var khtml = /KHTML\//.test(navigator.userAgent);
  var mac_geLion = /Mac OS X 1\d\D([7-9]|\d\d)\D/.test(navigator.userAgent);
  var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
  var phantom = /PhantomJS/.test(navigator.userAgent);

  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
  // This is woefully incomplete. Suggestions for alternative methods welcome.
  var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
  var mac = ios || /Mac/.test(navigator.platform);
  var windows = /windows/i.test(navigator.platform);

  var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
  if (opera_version) opera_version = Number(opera_version[1]);
  // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
  var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
  var captureMiddleClick = gecko || (ie && !ie_lt9);

  // Optimize some code when these features are not used
  var sawReadOnlySpans = false, sawCollapsedSpans = false;

  // CONSTRUCTOR

  function CodeMirror(place, options) {
    if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);

    this.options = options = options || {};
    // Determine effective options based on given values and defaults.
    for (var opt in defaults) if (!options.hasOwnProperty(opt) && defaults.hasOwnProperty(opt))
      options[opt] = defaults[opt];
    setGuttersForLineNumbers(options);

    var docStart = typeof options.value == "string" ? 0 : options.value.first;
    var display = this.display = makeDisplay(place, docStart);
    display.wrapper.CodeMirror = this;
    updateGutters(this);
    if (options.autofocus && !mobile) focusInput(this);

    this.state = {keyMaps: [],
                  overlays: [],
                  modeGen: 0,
                  overwrite: false, focused: false,
                  suppressEdits: false, pasteIncoming: false,
                  draggingText: false,
                  highlight: new Delayed()};

    themeChanged(this);
    if (options.lineWrapping)
      this.display.wrapper.className += " CodeMirror-wrap";

    var doc = options.value;
    if (typeof doc == "string") doc = new Doc(options.value, options.mode);
    operation(this, attachDoc)(this, doc);

    // Override magic textarea content restore that IE sometimes does
    // on our hidden textarea on reload
    if (ie) setTimeout(bind(resetInput, this, true), 20);

    registerEventHandlers(this);
    // IE throws unspecified error in certain cases, when
    // trying to access activeElement before onload
    var hasFocus; try { hasFocus = (document.activeElement == display.input); } catch(e) { }
    if (hasFocus || (options.autofocus && !mobile)) setTimeout(bind(onFocus, this), 20);
    else onBlur(this);

    operation(this, function() {
      for (var opt in optionHandlers)
        if (optionHandlers.propertyIsEnumerable(opt))
          optionHandlers[opt](this, options[opt], Init);
      for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
    })();
  }

  // DISPLAY CONSTRUCTOR

  function makeDisplay(place, docStart) {
    var d = {};

    var input = d.input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none; font-size: 4px;");
    if (webkit) input.style.width = "1000px";
    else input.setAttribute("wrap", "off");
    // if border: 0; -- iOS fails to open keyboard (issue #1287)
    if (ios) input.style.border = "1px solid black";
    input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); input.setAttribute("spellcheck", "false");

    // Wraps and hides input textarea
    d.inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
    // The actual fake scrollbars.
    d.scrollbarH = elt("div", [elt("div", null, null, "height: 1px")], "CodeMirror-hscrollbar");
    d.scrollbarV = elt("div", [elt("div", null, null, "width: 1px")], "CodeMirror-vscrollbar");
    d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
    d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
    // DIVs containing the selection and the actual code
    d.lineDiv = elt("div", null, "CodeMirror-code");
    d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
    // Blinky cursor, and element used to ensure cursor fits at the end of a line
    d.cursor = elt("div", "\u00a0", "CodeMirror-cursor");
    // Secondary cursor, shown when on a 'jump' in bi-directional text
    d.otherCursor = elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor");
    // Used to measure text size
    d.measure = elt("div", null, "CodeMirror-measure");
    // Wraps everything that needs to exist inside the vertically-padded coordinate system
    d.lineSpace = elt("div", [d.measure, d.selectionDiv, d.lineDiv, d.cursor, d.otherCursor],
                         null, "position: relative; outline: none");
    // Moved around its parent to cover visible view
    d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
    // Set to the height of the text, causes scrolling
    d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
    // D is needed because behavior of elts with overflow: auto and padding is inconsistent across browsers
    d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerCutOff + "px; width: 1px;");
    // Will contain the gutters, if any
    d.gutters = elt("div", null, "CodeMirror-gutters");
    d.lineGutter = null;
    // Provides scrolling
    d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
    d.scroller.setAttribute("tabIndex", "-1");
    // The element in which the editor lives.
    d.wrapper = elt("div", [d.inputDiv, d.scrollbarH, d.scrollbarV,
                            d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
    // Work around IE7 z-index bug
    if (ie_lt8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
    if (place.appendChild) place.appendChild(d.wrapper); else place(d.wrapper);

    // Needed to hide big blue blinking cursor on Mobile Safari
    if (ios) input.style.width = "0px";
    if (!webkit) d.scroller.draggable = true;
    // Needed to handle Tab key in KHTML
    if (khtml) { d.inputDiv.style.height = "1px"; d.inputDiv.style.position = "absolute"; }
    // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
    else if (ie_lt8) d.scrollbarH.style.minWidth = d.scrollbarV.style.minWidth = "18px";

    // Current visible range (may be bigger than the view window).
    d.viewOffset = d.lastSizeC = 0;
    d.showingFrom = d.showingTo = docStart;

    // Used to only resize the line number gutter when necessary (when
    // the amount of lines crosses a boundary that makes its width change)
    d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
    // See readInput and resetInput
    d.prevInput = "";
    // Set to true when a non-horizontal-scrolling widget is added. As
    // an optimization, widget aligning is skipped when d is false.
    d.alignWidgets = false;
    // Flag that indicates whether we currently expect input to appear
    // (after some event like 'keypress' or 'input') and are polling
    // intensively.
    d.pollingFast = false;
    // Self-resetting timeout for the poller
    d.poll = new Delayed();

    d.cachedCharWidth = d.cachedTextHeight = null;
    d.measureLineCache = [];
    d.measureLineCachePos = 0;

    // Tracks when resetInput has punted to just putting a short
    // string instead of the (large) selection.
    d.inaccurateSelection = false;

    // Tracks the maximum line length so that the horizontal scrollbar
    // can be kept static when scrolling.
    d.maxLine = null;
    d.maxLineLength = 0;
    d.maxLineChanged = false;

    // Used for measuring wheel scrolling granularity
    d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;

    return d;
  }

  // STATE UPDATES

  // Used to get the editor into a consistent state again when options change.

  function loadMode(cm) {
    cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
    cm.doc.iter(function(line) {
      if (line.stateAfter) line.stateAfter = null;
      if (line.styles) line.styles = null;
    });
    cm.doc.frontier = cm.doc.first;
    startWorker(cm, 100);
    cm.state.modeGen++;
    if (cm.curOp) regChange(cm);
  }

  function wrappingChanged(cm) {
    if (cm.options.lineWrapping) {
      cm.display.wrapper.className += " CodeMirror-wrap";
      cm.display.sizer.style.minWidth = "";
    } else {
      cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-wrap", "");
      computeMaxLength(cm);
    }
    estimateLineHeights(cm);
    regChange(cm);
    clearCaches(cm);
    setTimeout(function(){updateScrollbars(cm);}, 100);
  }

  function estimateHeight(cm) {
    var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
    var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
    return function(line) {
      if (lineIsHidden(cm.doc, line))
        return 0;
      else if (wrapping)
        return (Math.ceil(line.text.length / perLine) || 1) * th;
      else
        return th;
    };
  }

  function estimateLineHeights(cm) {
    var doc = cm.doc, est = estimateHeight(cm);
    doc.iter(function(line) {
      var estHeight = est(line);
      if (estHeight != line.height) updateLineHeight(line, estHeight);
    });
  }

  function keyMapChanged(cm) {
    var map = keyMap[cm.options.keyMap], style = map.style;
    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
      (style ? " cm-keymap-" + style : "");
    cm.state.disableInput = map.disableInput;
  }

  function themeChanged(cm) {
    cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
      cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
    clearCaches(cm);
  }

  function guttersChanged(cm) {
    updateGutters(cm);
    regChange(cm);
    setTimeout(function(){alignHorizontally(cm);}, 20);
  }

  function updateGutters(cm) {
    var gutters = cm.display.gutters, specs = cm.options.gutters;
    removeChildren(gutters);
    for (var i = 0; i < specs.length; ++i) {
      var gutterClass = specs[i];
      var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
      if (gutterClass == "CodeMirror-linenumbers") {
        cm.display.lineGutter = gElt;
        gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
      }
    }
    gutters.style.display = i ? "" : "none";
  }

  function lineLength(doc, line) {
    if (line.height == 0) return 0;
    var len = line.text.length, merged, cur = line;
    while (merged = collapsedSpanAtStart(cur)) {
      var found = merged.find();
      cur = getLine(doc, found.from.line);
      len += found.from.ch - found.to.ch;
    }
    cur = line;
    while (merged = collapsedSpanAtEnd(cur)) {
      var found = merged.find();
      len -= cur.text.length - found.from.ch;
      cur = getLine(doc, found.to.line);
      len += cur.text.length - found.to.ch;
    }
    return len;
  }

  function computeMaxLength(cm) {
    var d = cm.display, doc = cm.doc;
    d.maxLine = getLine(doc, doc.first);
    d.maxLineLength = lineLength(doc, d.maxLine);
    d.maxLineChanged = true;
    doc.iter(function(line) {
      var len = lineLength(doc, line);
      if (len > d.maxLineLength) {
        d.maxLineLength = len;
        d.maxLine = line;
      }
    });
  }

  // Make sure the gutters options contains the element
  // "CodeMirror-linenumbers" when the lineNumbers option is true.
  function setGuttersForLineNumbers(options) {
    var found = false;
    for (var i = 0; i < options.gutters.length; ++i) {
      if (options.gutters[i] == "CodeMirror-linenumbers") {
        if (options.lineNumbers) found = true;
        else options.gutters.splice(i--, 1);
      }
    }
    if (!found && options.lineNumbers)
      options.gutters.push("CodeMirror-linenumbers");
  }

  // SCROLLBARS

  // Re-synchronize the fake scrollbars with the actual size of the
  // content. Optionally force a scrollTop.
  function updateScrollbars(cm) {
    var d = cm.display, docHeight = cm.doc.height;
    var totalHeight = docHeight + paddingVert(d);
    d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
    d.gutters.style.height = Math.max(totalHeight, d.scroller.clientHeight - scrollerCutOff) + "px";
    var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
    var needsH = d.scroller.scrollWidth > (d.scroller.clientWidth + 1);
    var needsV = scrollHeight > (d.scroller.clientHeight + 1);
    if (needsV) {
      d.scrollbarV.style.display = "block";
      d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
      d.scrollbarV.firstChild.style.height =
        (scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
    } else d.scrollbarV.style.display = "";
    if (needsH) {
      d.scrollbarH.style.display = "block";
      d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
      d.scrollbarH.firstChild.style.width =
        (d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
    } else d.scrollbarH.style.display = "";
    if (needsH && needsV) {
      d.scrollbarFiller.style.display = "block";
      d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
    } else d.scrollbarFiller.style.display = "";
    if (needsH && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
      d.gutterFiller.style.display = "block";
      d.gutterFiller.style.height = scrollbarWidth(d.measure) + "px";
      d.gutterFiller.style.width = d.gutters.offsetWidth + "px";
    } else d.gutterFiller.style.display = "";

    if (mac_geLion && scrollbarWidth(d.measure) === 0)
      d.scrollbarV.style.minWidth = d.scrollbarH.style.minHeight = mac_geMountainLion ? "18px" : "12px";
  }

  function visibleLines(display, doc, viewPort) {
    var top = display.scroller.scrollTop, height = display.wrapper.clientHeight;
    if (typeof viewPort == "number") top = viewPort;
    else if (viewPort) {top = viewPort.top; height = viewPort.bottom - viewPort.top;}
    top = Math.floor(top - paddingTop(display));
    var bottom = Math.ceil(top + height);
    return {from: lineAtHeight(doc, top), to: lineAtHeight(doc, bottom)};
  }

  // LINE NUMBERS

  function alignHorizontally(cm) {
    var display = cm.display;
    if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
    var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
    var gutterW = display.gutters.offsetWidth, l = comp + "px";
    for (var n = display.lineDiv.firstChild; n; n = n.nextSibling) if (n.alignable) {
      for (var i = 0, a = n.alignable; i < a.length; ++i) a[i].style.left = l;
    }
    if (cm.options.fixedGutter)
      display.gutters.style.left = (comp + gutterW) + "px";
  }

  function maybeUpdateLineNumberWidth(cm) {
    if (!cm.options.lineNumbers) return false;
    var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
    if (last.length != display.lineNumChars) {
      var test = display.measure.appendChild(elt("div", [elt("div", last)],
                                                 "CodeMirror-linenumber CodeMirror-gutter-elt"));
      var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
      display.lineGutter.style.width = "";
      display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding);
      display.lineNumWidth = display.lineNumInnerWidth + padding;
      display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
      display.lineGutter.style.width = display.lineNumWidth + "px";
      return true;
    }
    return false;
  }

  function lineNumberFor(options, i) {
    return String(options.lineNumberFormatter(i + options.firstLineNumber));
  }
  function compensateForHScroll(display) {
    return getRect(display.scroller).left - getRect(display.sizer).left;
  }

  // DISPLAY DRAWING

  function updateDisplay(cm, changes, viewPort) {
    var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
    var visible = visibleLines(cm.display, cm.doc, viewPort);
    for (;;) {
      if (!updateDisplayInner(cm, changes, visible)) break;
      updated = true;
      updateSelection(cm);
      updateScrollbars(cm);

      // Clip forced viewport to actual scrollable area
      if (viewPort)
        viewPort = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight,
                            typeof viewPort == "number" ? viewPort : viewPort.top);
      visible = visibleLines(cm.display, cm.doc, viewPort);
      if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
        break;
      changes = [];
    }

    if (updated) {
      signalLater(cm, "update", cm);
      if (cm.display.showingFrom != oldFrom || cm.display.showingTo != oldTo)
        signalLater(cm, "viewportChange", cm, cm.display.showingFrom, cm.display.showingTo);
    }
    return updated;
  }

  // Uses a set of changes plus the current scroll position to
  // determine which DOM updates have to be made, and makes the
  // updates.
  function updateDisplayInner(cm, changes, visible) {
    var display = cm.display, doc = cm.doc;
    if (!display.wrapper.clientWidth) {
      display.showingFrom = display.showingTo = doc.first;
      display.viewOffset = 0;
      return;
    }

    // Bail out if the visible area is already rendered and nothing changed.
    if (changes.length == 0 &&
        visible.from > display.showingFrom && visible.to < display.showingTo)
      return;

    if (maybeUpdateLineNumberWidth(cm))
      changes = [{from: doc.first, to: doc.first + doc.size}];
    var gutterW = display.sizer.style.marginLeft = display.gutters.offsetWidth + "px";
    display.scrollbarH.style.left = cm.options.fixedGutter ? gutterW : "0";

    // Used to determine which lines need their line numbers updated
    var positionsChangedFrom = Infinity;
    if (cm.options.lineNumbers)
      for (var i = 0; i < changes.length; ++i)
        if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }

    var end = doc.first + doc.size;
    var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
    var to = Math.min(end, visible.to + cm.options.viewportMargin);
    if (display.showingFrom < from && from - display.showingFrom < 20) from = Math.max(doc.first, display.showingFrom);
    if (display.showingTo > to && display.showingTo - to < 20) to = Math.min(end, display.showingTo);
    if (sawCollapsedSpans) {
      from = lineNo(visualLine(doc, getLine(doc, from)));
      while (to < end && lineIsHidden(doc, getLine(doc, to))) ++to;
    }

    // Create a range of theoretically intact lines, and punch holes
    // in that using the change info.
    var intact = [{from: Math.max(display.showingFrom, doc.first),
                   to: Math.min(display.showingTo, end)}];
    if (intact[0].from >= intact[0].to) intact = [];
    else intact = computeIntact(intact, changes);
    // When merged lines are present, we might have to reduce the
    // intact ranges because changes in continued fragments of the
    // intact lines do require the lines to be redrawn.
    if (sawCollapsedSpans)
      for (var i = 0; i < intact.length; ++i) {
        var range = intact[i], merged;
        while (merged = collapsedSpanAtEnd(getLine(doc, range.to - 1))) {
          var newTo = merged.find().from.line;
          if (newTo > range.from) range.to = newTo;
          else { intact.splice(i--, 1); break; }
        }
      }

    // Clip off the parts that won't be visible
    var intactLines = 0;
    for (var i = 0; i < intact.length; ++i) {
      var range = intact[i];
      if (range.from < from) range.from = from;
      if (range.to > to) range.to = to;
      if (range.from >= range.to) intact.splice(i--, 1);
      else intactLines += range.to - range.from;
    }
    if (intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
      updateViewOffset(cm);
      return;
    }
    intact.sort(function(a, b) {return a.from - b.from;});

    // Avoid crashing on IE's "unspecified error" when in iframes
    try {
      var focused = document.activeElement;
    } catch(e) {}
    if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
    patchDisplay(cm, from, to, intact, positionsChangedFrom);
    display.lineDiv.style.display = "";
    if (focused && document.activeElement != focused && focused.offsetHeight) focused.focus();

    var different = from != display.showingFrom || to != display.showingTo ||
      display.lastSizeC != display.wrapper.clientHeight;
    // This is just a bogus formula that detects when the editor is
    // resized or the font size changes.
    if (different) {
      display.lastSizeC = display.wrapper.clientHeight;
      startWorker(cm, 400);
    }
    display.showingFrom = from; display.showingTo = to;

    var prevBottom = display.lineDiv.offsetTop;
    for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
      if (ie_lt8) {
        var bot = node.offsetTop + node.offsetHeight;
        height = bot - prevBottom;
        prevBottom = bot;
      } else {
        var box = getRect(node);
        height = box.bottom - box.top;
      }
      var diff = node.lineObj.height - height;
      if (height < 2) height = textHeight(display);
      if (diff > .001 || diff < -.001) {
        updateLineHeight(node.lineObj, height);
        var widgets = node.lineObj.widgets;
        if (widgets) for (var i = 0; i < widgets.length; ++i)
          widgets[i].height = widgets[i].node.offsetHeight;
      }
    }
    updateViewOffset(cm);

    return true;
  }

  function updateViewOffset(cm) {
    var off = cm.display.viewOffset = heightAtLine(cm, getLine(cm.doc, cm.display.showingFrom));
    // Position the mover div to align with the current virtual scroll position
    cm.display.mover.style.top = off + "px";
  }

  function computeIntact(intact, changes) {
    for (var i = 0, l = changes.length || 0; i < l; ++i) {
      var change = changes[i], intact2 = [], diff = change.diff || 0;
      for (var j = 0, l2 = intact.length; j < l2; ++j) {
        var range = intact[j];
        if (change.to <= range.from && change.diff) {
          intact2.push({from: range.from + diff, to: range.to + diff});
        } else if (change.to <= range.from || change.from >= range.to) {
          intact2.push(range);
        } else {
          if (change.from > range.from)
            intact2.push({from: range.from, to: change.from});
          if (change.to < range.to)
            intact2.push({from: change.to + diff, to: range.to + diff});
        }
      }
      intact = intact2;
    }
    return intact;
  }

  function getDimensions(cm) {
    var d = cm.display, left = {}, width = {};
    for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
      left[cm.options.gutters[i]] = n.offsetLeft;
      width[cm.options.gutters[i]] = n.offsetWidth;
    }
    return {fixedPos: compensateForHScroll(d),
            gutterTotalWidth: d.gutters.offsetWidth,
            gutterLeft: left,
            gutterWidth: width,
            wrapperWidth: d.wrapper.clientWidth};
  }

  function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
    var dims = getDimensions(cm);
    var display = cm.display, lineNumbers = cm.options.lineNumbers;
    if (!intact.length && (!webkit || !cm.display.currentWheelTarget))
      removeChildren(display.lineDiv);
    var container = display.lineDiv, cur = container.firstChild;

    function rm(node) {
      var next = node.nextSibling;
      if (webkit && mac && cm.display.currentWheelTarget == node) {
        node.style.display = "none";
        node.lineObj = null;
      } else {
        node.parentNode.removeChild(node);
      }
      return next;
    }

    var nextIntact = intact.shift(), lineN = from;
    cm.doc.iter(from, to, function(line) {
      if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
      if (lineIsHidden(cm.doc, line)) {
        if (line.height != 0) updateLineHeight(line, 0);
        if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
          var w = line.widgets[i];
          if (w.showIfHidden) {
            var prev = cur.previousSibling;
            if (/pre/i.test(prev.nodeName)) {
              var wrap = elt("div", null, null, "position: relative");
              prev.parentNode.replaceChild(wrap, prev);
              wrap.appendChild(prev);
              prev = wrap;
            }
            var wnode = prev.appendChild(elt("div", [w.node], "CodeMirror-linewidget"));
            if (!w.handleMouseEvents) wnode.ignoreEvents = true;
            positionLineWidget(w, wnode, prev, dims);
          }
        }
      } else if (nextIntact && nextIntact.from <= lineN && nextIntact.to > lineN) {
        // This line is intact. Skip to the actual node. Update its
        // line number if needed.
        while (cur.lineObj != line) cur = rm(cur);
        if (lineNumbers && updateNumbersFrom <= lineN && cur.lineNumber)
          setTextContent(cur.lineNumber, lineNumberFor(cm.options, lineN));
        cur = cur.nextSibling;
      } else {
        // For lines with widgets, make an attempt to find and reuse
        // the existing element, so that widgets aren't needlessly
        // removed and re-inserted into the dom
        if (line.widgets) for (var j = 0, search = cur, reuse; search && j < 20; ++j, search = search.nextSibling)
          if (search.lineObj == line && /div/i.test(search.nodeName)) { reuse = search; break; }
        // This line needs to be generated.
        var lineNode = buildLineElement(cm, line, lineN, dims, reuse);
        if (lineNode != reuse) {
          container.insertBefore(lineNode, cur);
        } else {
          while (cur != reuse) cur = rm(cur);
          cur = cur.nextSibling;
        }

        lineNode.lineObj = line;
      }
      ++lineN;
    });
    while (cur) cur = rm(cur);
  }

  function buildLineElement(cm, line, lineNo, dims, reuse) {
    var lineElement = lineContent(cm, line);
    var markers = line.gutterMarkers, display = cm.display, wrap;

    if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
      return lineElement;

    // Lines with gutter elements, widgets or a background class need
    // to be wrapped again, and have the extra elements added to the
    // wrapper div

    if (reuse) {
      reuse.alignable = null;
      var isOk = true, widgetsSeen = 0, insertBefore = null;
      for (var n = reuse.firstChild, next; n; n = next) {
        next = n.nextSibling;
        if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
          reuse.removeChild(n);
        } else {
          for (var i = 0, first = true; i < line.widgets.length; ++i) {
            var widget = line.widgets[i];
            if (!widget.above) { insertBefore = n; first = false; }
            if (widget.node == n.firstChild) {
              positionLineWidget(widget, n, reuse, dims);
              ++widgetsSeen;
              break;
            }
          }
          if (i == line.widgets.length) { isOk = false; break; }
        }
      }
      reuse.insertBefore(lineElement, insertBefore);
      if (isOk && widgetsSeen == line.widgets.length) {
        wrap = reuse;
        reuse.className = line.wrapClass || "";
      }
    }
    if (!wrap) {
      wrap = elt("div", null, line.wrapClass, "position: relative");
      wrap.appendChild(lineElement);
    }
    // Kludge to make sure the styled element lies behind the selection (by z-index)
    if (line.bgClass)
      wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
    if (cm.options.lineNumbers || markers) {
      var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
                                             (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
                                         wrap.firstChild);
      if (cm.options.fixedGutter) (wrap.alignable || (wrap.alignable = [])).push(gutterWrap);
      if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
        wrap.lineNumber = gutterWrap.appendChild(
          elt("div", lineNumberFor(cm.options, lineNo),
              "CodeMirror-linenumber CodeMirror-gutter-elt",
              "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
              + display.lineNumInnerWidth + "px"));
      if (markers)
        for (var k = 0; k < cm.options.gutters.length; ++k) {
          var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
          if (found)
            gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
                                       dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
        }
    }
    if (ie_lt8) wrap.style.zIndex = 2;
    if (line.widgets && wrap != reuse) for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
      var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
      if (!widget.handleMouseEvents) node.ignoreEvents = true;
      positionLineWidget(widget, node, wrap, dims);
      if (widget.above)
        wrap.insertBefore(node, cm.options.lineNumbers && line.height != 0 ? gutterWrap : lineElement);
      else
        wrap.appendChild(node);
      signalLater(widget, "redraw");
    }
    return wrap;
  }

  function positionLineWidget(widget, node, wrap, dims) {
    if (widget.noHScroll) {
      (wrap.alignable || (wrap.alignable = [])).push(node);
      var width = dims.wrapperWidth;
      node.style.left = dims.fixedPos + "px";
      if (!widget.coverGutter) {
        width -= dims.gutterTotalWidth;
        node.style.paddingLeft = dims.gutterTotalWidth + "px";
      }
      node.style.width = width + "px";
    }
    if (widget.coverGutter) {
      node.style.zIndex = 5;
      node.style.position = "relative";
      if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
    }
  }

  // SELECTION / CURSOR

  function updateSelection(cm) {
    var display = cm.display;
    var collapsed = posEq(cm.doc.sel.from, cm.doc.sel.to);
    if (collapsed || cm.options.showCursorWhenSelecting)
      updateSelectionCursor(cm);
    else
      display.cursor.style.display = display.otherCursor.style.display = "none";
    if (!collapsed)
      updateSelectionRange(cm);
    else
      display.selectionDiv.style.display = "none";

    // Move the hidden textarea near the cursor to prevent scrolling artifacts
    if (cm.options.moveInputWithCursor) {
      var headPos = cursorCoords(cm, cm.doc.sel.head, "div");
      var wrapOff = getRect(display.wrapper), lineOff = getRect(display.lineDiv);
      display.inputDiv.style.top = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
                                                        headPos.top + lineOff.top - wrapOff.top)) + "px";
      display.inputDiv.style.left = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
                                                         headPos.left + lineOff.left - wrapOff.left)) + "px";
    }
  }

  // No selection, plain cursor
  function updateSelectionCursor(cm) {
    var display = cm.display, pos = cursorCoords(cm, cm.doc.sel.head, "div");
    display.cursor.style.left = pos.left + "px";
    display.cursor.style.top = pos.top + "px";
    display.cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
    display.cursor.style.display = "";

    if (pos.other) {
      display.otherCursor.style.display = "";
      display.otherCursor.style.left = pos.other.left + "px";
      display.otherCursor.style.top = pos.other.top + "px";
      display.otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
    } else { display.otherCursor.style.display = "none"; }
  }

  // Highlight selection
  function updateSelectionRange(cm) {
    var display = cm.display, doc = cm.doc, sel = cm.doc.sel;
    var fragment = document.createDocumentFragment();
    var clientWidth = display.lineSpace.offsetWidth, pl = paddingLeft(cm.display);

    function add(left, top, width, bottom) {
      if (top < 0) top = 0;
      fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
                               "px; top: " + top + "px; width: " + (width == null ? clientWidth - left : width) +
                               "px; height: " + (bottom - top) + "px"));
    }

    function drawForLine(line, fromArg, toArg) {
      var lineObj = getLine(doc, line);
      var lineLen = lineObj.text.length;
      var start, end;
      function coords(ch, bias) {
        return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
      }

      iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
        var leftPos = coords(from, "left"), rightPos, left, right;
        if (from == to) {
          rightPos = leftPos;
          left = right = leftPos.left;
        } else {
          rightPos = coords(to - 1, "right");
          if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
          left = leftPos.left;
          right = rightPos.right;
        }
        if (fromArg == null && from == 0) left = pl;
        if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
          add(left, leftPos.top, null, leftPos.bottom);
          left = pl;
          if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
        }
        if (toArg == null && to == lineLen) right = clientWidth;
        if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
          start = leftPos;
        if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
          end = rightPos;
        if (left < pl + 1) left = pl;
        add(left, rightPos.top, right - left, rightPos.bottom);
      });
      return {start: start, end: end};
    }

    if (sel.from.line == sel.to.line) {
      drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
    } else {
      var fromLine = getLine(doc, sel.from.line), toLine = getLine(doc, sel.to.line);
      var singleVLine = visualLine(doc, fromLine) == visualLine(doc, toLine);
      var leftEnd = drawForLine(sel.from.line, sel.from.ch, singleVLine ? fromLine.text.length : null).end;
      var rightStart = drawForLine(sel.to.line, singleVLine ? 0 : null, sel.to.ch).start;
      if (singleVLine) {
        if (leftEnd.top < rightStart.top - 2) {
          add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
          add(pl, rightStart.top, rightStart.left, rightStart.bottom);
        } else {
          add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
        }
      }
      if (leftEnd.bottom < rightStart.top)
        add(pl, leftEnd.bottom, null, rightStart.top);
    }

    removeChildrenAndAdd(display.selectionDiv, fragment);
    display.selectionDiv.style.display = "";
  }

  // Cursor-blinking
  function restartBlink(cm) {
    if (!cm.state.focused) return;
    var display = cm.display;
    clearInterval(display.blinker);
    var on = true;
    display.cursor.style.visibility = display.otherCursor.style.visibility = "";
    display.blinker = setInterval(function() {
      display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
    }, cm.options.cursorBlinkRate);
  }

  // HIGHLIGHT WORKER

  function startWorker(cm, time) {
    if (cm.doc.mode.startState && cm.doc.frontier < cm.display.showingTo)
      cm.state.highlight.set(time, bind(highlightWorker, cm));
  }

  function highlightWorker(cm) {
    var doc = cm.doc;
    if (doc.frontier < doc.first) doc.frontier = doc.first;
    if (doc.frontier >= cm.display.showingTo) return;
    var end = +new Date + cm.options.workTime;
    var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
    var changed = [], prevChange;
    doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.showingTo + 500), function(line) {
      if (doc.frontier >= cm.display.showingFrom) { // Visible
        var oldStyles = line.styles;
        line.styles = highlightLine(cm, line, state);
        var ischange = !oldStyles || oldStyles.length != line.styles.length;
        for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
        if (ischange) {
          if (prevChange && prevChange.end == doc.frontier) prevChange.end++;
          else changed.push(prevChange = {start: doc.frontier, end: doc.frontier + 1});
        }
        line.stateAfter = copyState(doc.mode, state);
      } else {
        processLine(cm, line, state);
        line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
      }
      ++doc.frontier;
      if (+new Date > end) {
        startWorker(cm, cm.options.workDelay);
        return true;
      }
    });
    if (changed.length)
      operation(cm, function() {
        for (var i = 0; i < changed.length; ++i)
          regChange(this, changed[i].start, changed[i].end);
      })();
  }

  // Finds the line to start with when starting a parse. Tries to
  // find a line with a stateAfter, so that it can start with a
  // valid state. If that fails, it returns the line with the
  // smallest indentation, which tends to need the least context to
  // parse correctly.
  function findStartLine(cm, n, precise) {
    var minindent, minline, doc = cm.doc;
    for (var search = n, lim = n - 100; search > lim; --search) {
      if (search <= doc.first) return doc.first;
      var line = getLine(doc, search - 1);
      if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
      var indented = countColumn(line.text, null, cm.options.tabSize);
      if (minline == null || minindent > indented) {
        minline = search - 1;
        minindent = indented;
      }
    }
    return minline;
  }

  function getStateBefore(cm, n, precise) {
    var doc = cm.doc, display = cm.display;
      if (!doc.mode.startState) return true;
    var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
    if (!state) state = startState(doc.mode);
    else state = copyState(doc.mode, state);
    doc.iter(pos, n, function(line) {
      processLine(cm, line, state);
      var save = pos == n - 1 || pos % 5 == 0 || pos >= display.showingFrom && pos < display.showingTo;
      line.stateAfter = save ? copyState(doc.mode, state) : null;
      ++pos;
    });
    return state;
  }

  // POSITION MEASUREMENT

  function paddingTop(display) {return display.lineSpace.offsetTop;}
  function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
  function paddingLeft(display) {
    var e = removeChildrenAndAdd(display.measure, elt("pre", null, null, "text-align: left")).appendChild(elt("span", "x"));
    return e.offsetLeft;
  }

  function measureChar(cm, line, ch, data, bias) {
    var dir = -1;
    data = data || measureLine(cm, line);

    for (var pos = ch;; pos += dir) {
      var r = data[pos];
      if (r) break;
      if (dir < 0 && pos == 0) dir = 1;
    }
    var rightV = (pos < ch || bias == "right") && r.topRight != null;
    return {left: pos < ch ? r.right : r.left,
            right: pos > ch ? r.left : r.right,
            top: rightV ? r.topRight : r.top,
            bottom: rightV ? r.bottomRight : r.bottom};
  }

  function findCachedMeasurement(cm, line) {
    var cache = cm.display.measureLineCache;
    for (var i = 0; i < cache.length; ++i) {
      var memo = cache[i];
      if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
          cm.display.scroller.clientWidth == memo.width &&
          memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
        return memo;
    }
  }

  function clearCachedMeasurement(cm, line) {
    var exists = findCachedMeasurement(cm, line);
    if (exists) exists.text = exists.measure = exists.markedSpans = null;
  }

  function measureLine(cm, line) {
    // First look in the cache
    var cached = findCachedMeasurement(cm, line);
    if (cached) return cached.measure;

    // Failing that, recompute and store result in cache
    var measure = measureLineInner(cm, line);
    var cache = cm.display.measureLineCache;
    var memo = {text: line.text, width: cm.display.scroller.clientWidth,
                markedSpans: line.markedSpans, measure: measure,
                classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
    if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
    else cache.push(memo);
    return measure;
  }

  function measureLineInner(cm, line) {
    var display = cm.display, measure = emptyArray(line.text.length);
    var pre = lineContent(cm, line, measure);

    // IE does not cache element positions of inline elements between
    // calls to getBoundingClientRect. This makes the loop below,
    // which gathers the positions of all the characters on the line,
    // do an amount of layout work quadratic to the number of
    // characters. When line wrapping is off, we try to improve things
    // by first subdividing the line into a bunch of inline blocks, so
    // that IE can reuse most of the layout information from caches
    // for those blocks. This does interfere with line wrapping, so it
    // doesn't work when wrapping is on, but in that case the
    // situation is slightly better, since IE does cache line-wrapping
    // information and only recomputes per-line.
    if (ie && !ie_lt8 && !cm.options.lineWrapping && pre.childNodes.length > 100) {
      var fragment = document.createDocumentFragment();
      var chunk = 10, n = pre.childNodes.length;
      for (var i = 0, chunks = Math.ceil(n / chunk); i < chunks; ++i) {
        var wrap = elt("div", null, null, "display: inline-block");
        for (var j = 0; j < chunk && n; ++j) {
          wrap.appendChild(pre.firstChild);
          --n;
        }
        fragment.appendChild(wrap);
      }
      pre.appendChild(fragment);
    }

    removeChildrenAndAdd(display.measure, pre);

    var outer = getRect(display.lineDiv);
    var vranges = [], data = emptyArray(line.text.length), maxBot = pre.offsetHeight;
    // Work around an IE7/8 bug where it will sometimes have randomly
    // replaced our pre with a clone at this point.
    if (ie_lt9 && display.measure.first != pre)
      removeChildrenAndAdd(display.measure, pre);

    function categorizeVSpan(top, bot) {
      if (bot > maxBot) bot = maxBot;
      if (top < 0) top = 0;
      for (var j = 0; j < vranges.length; j += 2) {
        var rtop = vranges[j], rbot = vranges[j+1];
        if (rtop > bot || rbot < top) continue;
        if (rtop <= top && rbot >= bot ||
            top <= rtop && bot >= rbot ||
            Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
          vranges[j] = Math.min(top, rtop);
          vranges[j+1] = Math.max(bot, rbot);
          return j;
        }
      }
      vranges.push(top, bot);
      return j;
    }

    for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
      var size, node = cur;
      // A widget might wrap, needs special care
      if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
        if (cur.firstChild.nodeType == 1) node = cur.firstChild;
        var rects = node.getClientRects(), rLeft = rects[0], rRight = rects[rects.length - 1];
        if (rects.length > 1) {
          var vCatLeft = categorizeVSpan(rLeft.top - outer.top, rLeft.bottom - outer.top);
          var vCatRight = categorizeVSpan(rRight.top - outer.top, rRight.bottom - outer.top);
          data[i] = {left: rLeft.left - outer.left, right: rRight.right - outer.left,
                     top: vCatLeft, topRight: vCatRight};
          continue;
        }
      }
      size = getRect(node);
      var vCat = categorizeVSpan(size.top - outer.top, size.bottom - outer.top);
      var right = size.right;
      if (cur.measureRight) right = getRect(cur.measureRight).left;
      data[i] = {left: size.left - outer.left, right: right - outer.left, top: vCat};
    }
    for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
      var vr = cur.top, vrRight = cur.topRight;
      cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
      if (vrRight != null) { cur.topRight = vranges[vrRight]; cur.bottomRight = vranges[vrRight+1]; }
    }
    return data;
  }

  function measureLineWidth(cm, line) {
    var hasBadSpan = false;
    if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
      var sp = line.markedSpans[i];
      if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
    }
    var cached = !hasBadSpan && findCachedMeasurement(cm, line);
    if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;

    var pre = lineContent(cm, line);
    var end = pre.appendChild(zeroWidthElement(cm.display.measure));
    removeChildrenAndAdd(cm.display.measure, pre);
    return getRect(end).right - getRect(cm.display.lineDiv).left;
  }

  function clearCaches(cm) {
    cm.display.measureLineCache.length = cm.display.measureLineCachePos = 0;
    cm.display.cachedCharWidth = cm.display.cachedTextHeight = null;
    if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
    cm.display.lineNumChars = null;
  }

  function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
  function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }

  // Context is one of "line", "div" (display.lineDiv), "local"/null (editor), or "page"
  function intoCoordSystem(cm, lineObj, rect, context) {
    if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
      var size = widgetHeight(lineObj.widgets[i]);
      rect.top += size; rect.bottom += size;
    }
    if (context == "line") return rect;
    if (!context) context = "local";
    var yOff = heightAtLine(cm, lineObj);
    if (context == "local") yOff += paddingTop(cm.display);
    else yOff -= cm.display.viewOffset;
    if (context == "page" || context == "window") {
      var lOff = getRect(cm.display.lineSpace);
      yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
      var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
      rect.left += xOff; rect.right += xOff;
    }
    rect.top += yOff; rect.bottom += yOff;
    return rect;
  }

  // Context may be "window", "page", "div", or "local"/null
  // Result is in "div" coords
  function fromCoordSystem(cm, coords, context) {
    if (context == "div") return coords;
    var left = coords.left, top = coords.top;
    // First move into "page" coordinate system
    if (context == "page") {
      left -= pageScrollX();
      top -= pageScrollY();
    } else if (context == "local" || !context) {
      var localBox = getRect(cm.display.sizer);
      left += localBox.left;
      top += localBox.top;
    }

    var lineSpaceBox = getRect(cm.display.lineSpace);
    return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
  }

  function charCoords(cm, pos, context, lineObj, bias) {
    if (!lineObj) lineObj = getLine(cm.doc, pos.line);
    return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, null, bias), context);
  }

  function cursorCoords(cm, pos, context, lineObj, measurement) {
    lineObj = lineObj || getLine(cm.doc, pos.line);
    if (!measurement) measurement = measureLine(cm, lineObj);
    function get(ch, right) {
      var m = measureChar(cm, lineObj, ch, measurement, right ? "right" : "left");
      if (right) m.left = m.right; else m.right = m.left;
      return intoCoordSystem(cm, lineObj, m, context);
    }
    function getBidi(ch, partPos) {
      var part = order[partPos], right = part.level % 2;
      if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
        part = order[--partPos];
        ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
        right = true;
      } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
        part = order[++partPos];
        ch = bidiLeft(part) - part.level % 2;
        right = false;
      }
      if (right && ch == part.to && ch > part.from) return get(ch - 1);
      return get(ch, right);
    }
    var order = getOrder(lineObj), ch = pos.ch;
    if (!order) return get(ch);
    var partPos = getBidiPartAt(order, ch);
    var val = getBidi(ch, partPos);
    if (bidiOther != null) val.other = getBidi(ch, bidiOther);
    return val;
  }

  function PosWithInfo(line, ch, outside, xRel) {
    var pos = new Pos(line, ch);
    pos.xRel = xRel;
    if (outside) pos.outside = true;
    return pos;
  }

  // Coords must be lineSpace-local
  function coordsChar(cm, x, y) {
    var doc = cm.doc;
    y += cm.display.viewOffset;
    if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
    var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
    if (lineNo > last)
      return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
    if (x < 0) x = 0;

    for (;;) {
      var lineObj = getLine(doc, lineNo);
      var found = coordsCharInner(cm, lineObj, lineNo, x, y);
      var merged = collapsedSpanAtEnd(lineObj);
      var mergedPos = merged && merged.find();
      if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
        lineNo = mergedPos.to.line;
      else
        return found;
    }
  }

  function coordsCharInner(cm, lineObj, lineNo, x, y) {
    var innerOff = y - heightAtLine(cm, lineObj);
    var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
    var measurement = measureLine(cm, lineObj);

    function getX(ch) {
      var sp = cursorCoords(cm, Pos(lineNo, ch), "line",
                            lineObj, measurement);
      wrongLine = true;
      if (innerOff > sp.bottom) return sp.left - adjust;
      else if (innerOff < sp.top) return sp.left + adjust;
      else wrongLine = false;
      return sp.left;
    }

    var bidi = getOrder(lineObj), dist = lineObj.text.length;
    var from = lineLeft(lineObj), to = lineRight(lineObj);
    var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;

    if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
    // Do a binary search between these bounds.
    for (;;) {
      if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
        var ch = x < fromX || x - fromX <= toX - x ? from : to;
        var xDiff = x - (ch == from ? fromX : toX);
        while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
        var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
                              xDiff < 0 ? -1 : xDiff ? 1 : 0);
        return pos;
      }
      var step = Math.ceil(dist / 2), middle = from + step;
      if (bidi) {
        middle = from;
        for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
      }
      var middleX = getX(middle);
      if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
      else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
    }
  }

  var measureText;
  function textHeight(display) {
    if (display.cachedTextHeight != null) return display.cachedTextHeight;
    if (measureText == null) {
      measureText = elt("pre");
      // Measure a bunch of lines, for browsers that compute
      // fractional heights.
      for (var i = 0; i < 49; ++i) {
        measureText.appendChild(document.createTextNode("x"));
        measureText.appendChild(elt("br"));
      }
      measureText.appendChild(document.createTextNode("x"));
    }
    removeChildrenAndAdd(display.measure, measureText);
    var height = measureText.offsetHeight / 50;
    if (height > 3) display.cachedTextHeight = height;
    removeChildren(display.measure);
    return height || 1;
  }

  function charWidth(display) {
    if (display.cachedCharWidth != null) return display.cachedCharWidth;
    var anchor = elt("span", "x");
    var pre = elt("pre", [anchor]);
    removeChildrenAndAdd(display.measure, pre);
    var width = anchor.offsetWidth;
    if (width > 2) display.cachedCharWidth = width;
    return width || 10;
  }

  // OPERATIONS

  // Operations are used to wrap changes in such a way that each
  // change won't have to update the cursor and display (which would
  // be awkward, slow, and error-prone), but instead updates are
  // batched and then all combined and executed at once.

  var nextOpId = 0;
  function startOperation(cm) {
    cm.curOp = {
      // An array of ranges of lines that have to be updated. See
      // updateDisplay.
      changes: [],
      updateInput: null,
      userSelChange: null,
      textChanged: null,
      selectionChanged: false,
      cursorActivity: false,
      updateMaxLine: false,
      updateScrollPos: false,
      id: ++nextOpId
    };
    if (!delayedCallbackDepth++) delayedCallbacks = [];
  }

  function endOperation(cm) {
    var op = cm.curOp, doc = cm.doc, display = cm.display;
    cm.curOp = null;

    if (op.updateMaxLine) computeMaxLength(cm);
    if (display.maxLineChanged && !cm.options.lineWrapping && display.maxLine) {
      var width = measureLineWidth(cm, display.maxLine);
      display.sizer.style.minWidth = Math.max(0, width + 3 + scrollerCutOff) + "px";
      display.maxLineChanged = false;
      var maxScrollLeft = Math.max(0, display.sizer.offsetLeft + display.sizer.offsetWidth - display.scroller.clientWidth);
      if (maxScrollLeft < doc.scrollLeft && !op.updateScrollPos)
        setScrollLeft(cm, Math.min(display.scroller.scrollLeft, maxScrollLeft), true);
    }
    var newScrollPos, updated;
    if (op.updateScrollPos) {
      newScrollPos = op.updateScrollPos;
    } else if (op.selectionChanged && display.scroller.clientHeight) { // don't rescroll if not visible
      var coords = cursorCoords(cm, doc.sel.head);
      newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
    }
    if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null) {
      updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop);
      if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
    }
    if (!updated && op.selectionChanged) updateSelection(cm);
    if (op.updateScrollPos) {
      display.scroller.scrollTop = display.scrollbarV.scrollTop = doc.scrollTop = newScrollPos.scrollTop;
      display.scroller.scrollLeft = display.scrollbarH.scrollLeft = doc.scrollLeft = newScrollPos.scrollLeft;
      alignHorizontally(cm);
      if (op.scrollToPos)
        scrollPosIntoView(cm, clipPos(cm.doc, op.scrollToPos), op.scrollToPosMargin);
    } else if (newScrollPos) {
      scrollCursorIntoView(cm);
    }
    if (op.selectionChanged) restartBlink(cm);

    if (cm.state.focused && op.updateInput)
      resetInput(cm, op.userSelChange);

    var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
    if (hidden) for (var i = 0; i < hidden.length; ++i)
      if (!hidden[i].lines.length) signal(hidden[i], "hide");
    if (unhidden) for (var i = 0; i < unhidden.length; ++i)
      if (unhidden[i].lines.length) signal(unhidden[i], "unhide");

    var delayed;
    if (!--delayedCallbackDepth) {
      delayed = delayedCallbacks;
      delayedCallbacks = null;
    }
    if (op.textChanged)
      signal(cm, "change", cm, op.textChanged);
    if (op.cursorActivity) signal(cm, "cursorActivity", cm);
    if (delayed) for (var i = 0; i < delayed.length; ++i) delayed[i]();
  }

  // Wraps a function in an operation. Returns the wrapped function.
  function operation(cm1, f) {
    return function() {
      var cm = cm1 || this, withOp = !cm.curOp;
      if (withOp) startOperation(cm);
      try { var result = f.apply(cm, arguments); }
      finally { if (withOp) endOperation(cm); }
      return result;
    };
  }
  function docOperation(f) {
    return function() {
      var withOp = this.cm && !this.cm.curOp, result;
      if (withOp) startOperation(this.cm);
      try { result = f.apply(this, arguments); }
      finally { if (withOp) endOperation(this.cm); }
      return result;
    };
  }
  function runInOp(cm, f) {
    var withOp = !cm.curOp, result;
    if (withOp) startOperation(cm);
    try { result = f(); }
    finally { if (withOp) endOperation(cm); }
    return result;
  }

  function regChange(cm, from, to, lendiff) {
    if (from == null) from = cm.doc.first;
    if (to == null) to = cm.doc.first + cm.doc.size;
    cm.curOp.changes.push({from: from, to: to, diff: lendiff});
  }

  // INPUT HANDLING

  function slowPoll(cm) {
    if (cm.display.pollingFast) return;
    cm.display.poll.set(cm.options.pollInterval, function() {
      readInput(cm);
      if (cm.state.focused) slowPoll(cm);
    });
  }

  function fastPoll(cm) {
    var missed = false;
    cm.display.pollingFast = true;
    function p() {
      var changed = readInput(cm);
      if (!changed && !missed) {missed = true; cm.display.poll.set(60, p);}
      else {cm.display.pollingFast = false; slowPoll(cm);}
    }
    cm.display.poll.set(20, p);
  }

  // prevInput is a hack to work with IME. If we reset the textarea
  // on every change, that breaks IME. So we look for changes
  // compared to the previous content instead. (Modern browsers have
  // events that indicate IME taking place, but these are not widely
  // supported or compatible enough yet to rely on.)
  function readInput(cm) {
    var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
    if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
    var text = input.value;
    if (text == prevInput && posEq(sel.from, sel.to)) return false;
    if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
      resetInput(cm, true);
      return false;
    }

    var withOp = !cm.curOp;
    if (withOp) startOperation(cm);
    sel.shift = false;
    var same = 0, l = Math.min(prevInput.length, text.length);
    while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
    var from = sel.from, to = sel.to;
    if (same < prevInput.length)
      from = Pos(from.line, from.ch - (prevInput.length - same));
    else if (cm.state.overwrite && posEq(from, to) && !cm.state.pasteIncoming)
      to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + (text.length - same)));

    var updateInput = cm.curOp.updateInput;
    var changeEvent = {from: from, to: to, text: splitLines(text.slice(same)),
                       origin: cm.state.pasteIncoming ? "paste" : "+input"};
    makeChange(cm.doc, changeEvent, "end");
    cm.curOp.updateInput = updateInput;
    signalLater(cm, "inputRead", cm, changeEvent);

    if (text.length > 1000 || text.indexOf("\n") > -1) input.value = cm.display.prevInput = "";
    else cm.display.prevInput = text;
    if (withOp) endOperation(cm);
    cm.state.pasteIncoming = false;
    return true;
  }

  function resetInput(cm, user) {
    var minimal, selected, doc = cm.doc;
    if (!posEq(doc.sel.from, doc.sel.to)) {
      cm.display.prevInput = "";
      minimal = hasCopyEvent &&
        (doc.sel.to.line - doc.sel.from.line > 100 || (selected = cm.getSelection()).length > 1000);
      var content = minimal ? "-" : selected || cm.getSelection();
      cm.display.input.value = content;
      if (cm.state.focused) selectInput(cm.display.input);
      if (ie && !ie_lt9) cm.display.inputHasSelection = content;
    } else if (user) {
      cm.display.prevInput = cm.display.input.value = "";
      if (ie && !ie_lt9) cm.display.inputHasSelection = null;
    }
    cm.display.inaccurateSelection = minimal;
  }

  function focusInput(cm) {
    if (cm.options.readOnly != "nocursor" && (!mobile || document.activeElement != cm.display.input))
      cm.display.input.focus();
  }

  function isReadOnly(cm) {
    return cm.options.readOnly || cm.doc.cantEdit;
  }

  // EVENT HANDLERS

  function registerEventHandlers(cm) {
    var d = cm.display;
    on(d.scroller, "mousedown", operation(cm, onMouseDown));
    if (ie)
      on(d.scroller, "dblclick", operation(cm, function(e) {
        if (signalDOMEvent(cm, e)) return;
        var pos = posFromMouse(cm, e);
        if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
        e_preventDefault(e);
        var word = findWordAt(getLine(cm.doc, pos.line).text, pos);
        extendSelection(cm.doc, word.from, word.to);
      }));
    else
      on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
    on(d.lineSpace, "selectstart", function(e) {
      if (!eventInWidget(d, e)) e_preventDefault(e);
    });
    // Gecko browsers fire contextmenu *after* opening the menu, at
    // which point we can't mess with it anymore. Context menu is
    // handled in onMouseDown for Gecko.
    if (!captureMiddleClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});

    on(d.scroller, "scroll", function() {
      if (d.scroller.clientHeight) {
        setScrollTop(cm, d.scroller.scrollTop);
        setScrollLeft(cm, d.scroller.scrollLeft, true);
        signal(cm, "scroll", cm);
      }
    });
    on(d.scrollbarV, "scroll", function() {
      if (d.scroller.clientHeight) setScrollTop(cm, d.scrollbarV.scrollTop);
    });
    on(d.scrollbarH, "scroll", function() {
      if (d.scroller.clientHeight) setScrollLeft(cm, d.scrollbarH.scrollLeft);
    });

    on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
    on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});

    function reFocus() { if (cm.state.focused) setTimeout(bind(focusInput, cm), 0); }
    on(d.scrollbarH, "mousedown", reFocus);
    on(d.scrollbarV, "mousedown", reFocus);
    // Prevent wrapper from ever scrolling
    on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });

    var resizeTimer;
    function onResize() {
      if (resizeTimer == null) resizeTimer = setTimeout(function() {
        resizeTimer = null;
        // Might be a text scaling operation, clear size caches.
        d.cachedCharWidth = d.cachedTextHeight = knownScrollbarWidth = null;
        clearCaches(cm);
        runInOp(cm, bind(regChange, cm));
      }, 100);
    }
    on(window, "resize", onResize);
    // Above handler holds on to the editor and its data structures.
    // Here we poll to unregister it when the editor is no longer in
    // the document, so that it can be garbage-collected.
    function unregister() {
      for (var p = d.wrapper.parentNode; p && p != document.body; p = p.parentNode) {}
      if (p) setTimeout(unregister, 5000);
      else off(window, "resize", onResize);
    }
    setTimeout(unregister, 5000);

    on(d.input, "keyup", operation(cm, function(e) {
      if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
      if (e.keyCode == 16) cm.doc.sel.shift = false;
    }));
    on(d.input, "input", bind(fastPoll, cm));
    on(d.input, "keydown", operation(cm, onKeyDown));
    on(d.input, "keypress", operation(cm, onKeyPress));
    on(d.input, "focus", bind(onFocus, cm));
    on(d.input, "blur", bind(onBlur, cm));

    function drag_(e) {
      if (signalDOMEvent(cm, e) || cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))) return;
      e_stop(e);
    }
    if (cm.options.dragDrop) {
      on(d.scroller, "dragstart", function(e){onDragStart(cm, e);});
      on(d.scroller, "dragenter", drag_);
      on(d.scroller, "dragover", drag_);
      on(d.scroller, "drop", operation(cm, onDrop));
    }
    on(d.scroller, "paste", function(e){
      if (eventInWidget(d, e)) return;
      focusInput(cm);
      fastPoll(cm);
    });
    on(d.input, "paste", function() {
      cm.state.pasteIncoming = true;
      fastPoll(cm);
    });

    function prepareCopy() {
      if (d.inaccurateSelection) {
        d.prevInput = "";
        d.inaccurateSelection = false;
        d.input.value = cm.getSelection();
        selectInput(d.input);
      }
    }
    on(d.input, "cut", prepareCopy);
    on(d.input, "copy", prepareCopy);

    // Needed to handle Tab key in KHTML
    if (khtml) on(d.sizer, "mouseup", function() {
        if (document.activeElement == d.input) d.input.blur();
        focusInput(cm);
    });
  }

  function eventInWidget(display, e) {
    for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
      if (!n || n.ignoreEvents || n.parentNode == display.sizer && n != display.mover) return true;
    }
  }

  function posFromMouse(cm, e, liberal) {
    var display = cm.display;
    if (!liberal) {
      var target = e_target(e);
      if (target == display.scrollbarH || target == display.scrollbarH.firstChild ||
          target == display.scrollbarV || target == display.scrollbarV.firstChild ||
          target == display.scrollbarFiller || target == display.gutterFiller) return null;
    }
    var x, y, space = getRect(display.lineSpace);
    // Fails unpredictably on IE[67] when mouse is dragged around quickly.
    try { x = e.clientX; y = e.clientY; } catch (e) { return null; }
    return coordsChar(cm, x - space.left, y - space.top);
  }

  var lastClick, lastDoubleClick;
  function onMouseDown(e) {
    if (signalDOMEvent(this, e)) return;
    var cm = this, display = cm.display, doc = cm.doc, sel = doc.sel;
    sel.shift = e.shiftKey;

    if (eventInWidget(display, e)) {
      if (!webkit) {
        display.scroller.draggable = false;
        setTimeout(function(){display.scroller.draggable = true;}, 100);
      }
      return;
    }
    if (clickInGutter(cm, e)) return;
    var start = posFromMouse(cm, e);

    switch (e_button(e)) {
    case 3:
      if (captureMiddleClick) onContextMenu.call(cm, cm, e);
      return;
    case 2:
      if (start) extendSelection(cm.doc, start);
      setTimeout(bind(focusInput, cm), 20);
      e_preventDefault(e);
      return;
    }
    // For button 1, if it was clicked inside the editor
    // (posFromMouse returning non-null), we have to adjust the
    // selection.
    if (!start) {if (e_target(e) == display.scroller) e_preventDefault(e); return;}

    if (!cm.state.focused) onFocus(cm);

    var now = +new Date, type = "single";
    if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {
      type = "triple";
      e_preventDefault(e);
      setTimeout(bind(focusInput, cm), 20);
      selectLine(cm, start.line);
    } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {
      type = "double";
      lastDoubleClick = {time: now, pos: start};
      e_preventDefault(e);
      var word = findWordAt(getLine(doc, start.line).text, start);
      extendSelection(cm.doc, word.from, word.to);
    } else { lastClick = {time: now, pos: start}; }

    var last = start;
    if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && !posEq(sel.from, sel.to) &&
        !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") {
      var dragEnd = operation(cm, function(e2) {
        if (webkit) display.scroller.draggable = false;
        cm.state.draggingText = false;
        off(document, "mouseup", dragEnd);
        off(display.scroller, "drop", dragEnd);
        if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
          e_preventDefault(e2);
          extendSelection(cm.doc, start);
          focusInput(cm);
        }
      });
      // Let the drag handler handle this.
      if (webkit) display.scroller.draggable = true;
      cm.state.draggingText = dragEnd;
      // IE's approach to draggable
      if (display.scroller.dragDrop) display.scroller.dragDrop();
      on(document, "mouseup", dragEnd);
      on(display.scroller, "drop", dragEnd);
      return;
    }
    e_preventDefault(e);
    if (type == "single") extendSelection(cm.doc, clipPos(doc, start));

    var startstart = sel.from, startend = sel.to, lastPos = start;

    function doSelect(cur) {
      if (posEq(lastPos, cur)) return;
      lastPos = cur;

      if (type == "single") {
        extendSelection(cm.doc, clipPos(doc, start), cur);
        return;
      }

      startstart = clipPos(doc, startstart);
      startend = clipPos(doc, startend);
      if (type == "double") {
        var word = findWordAt(getLine(doc, cur.line).text, cur);
        if (posLess(cur, startstart)) extendSelection(cm.doc, word.from, startend);
        else extendSelection(cm.doc, startstart, word.to);
      } else if (type == "triple") {
        if (posLess(cur, startstart)) extendSelection(cm.doc, startend, clipPos(doc, Pos(cur.line, 0)));
        else extendSelection(cm.doc, startstart, clipPos(doc, Pos(cur.line + 1, 0)));
      }
    }

    var editorSize = getRect(display.wrapper);
    // Used to ensure timeout re-tries don't fire when another extend
    // happened in the meantime (clearTimeout isn't reliable -- at
    // least on Chrome, the timeouts still happen even when cleared,
    // if the clear happens after their scheduled firing time).
    var counter = 0;

    function extend(e) {
      var curCount = ++counter;
      var cur = posFromMouse(cm, e, true);
      if (!cur) return;
      if (!posEq(cur, last)) {
        if (!cm.state.focused) onFocus(cm);
        last = cur;
        doSelect(cur);
        var visible = visibleLines(display, doc);
        if (cur.line >= visible.to || cur.line < visible.from)
          setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
      } else {
        var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
        if (outside) setTimeout(operation(cm, function() {
          if (counter != curCount) return;
          display.scroller.scrollTop += outside;
          extend(e);
        }), 50);
      }
    }

    function done(e) {
      counter = Infinity;
      e_preventDefault(e);
      focusInput(cm);
      off(document, "mousemove", move);
      off(document, "mouseup", up);
    }

    var move = operation(cm, function(e) {
      if (!ie && !e_button(e)) done(e);
      else extend(e);
    });
    var up = operation(cm, done);
    on(document, "mousemove", move);
    on(document, "mouseup", up);
  }

  function clickInGutter(cm, e) {
    var display = cm.display;
    try { var mX = e.clientX, mY = e.clientY; }
    catch(e) { return false; }

    if (mX >= Math.floor(getRect(display.gutters).right)) return false;
    e_preventDefault(e);
    if (!hasHandler(cm, "gutterClick")) return true;

    var lineBox = getRect(display.lineDiv);
    if (mY > lineBox.bottom) return true;
    mY -= lineBox.top - display.viewOffset;

    for (var i = 0; i < cm.options.gutters.length; ++i) {
      var g = display.gutters.childNodes[i];
      if (g && getRect(g).right >= mX) {
        var line = lineAtHeight(cm.doc, mY);
        var gutter = cm.options.gutters[i];
        signalLater(cm, "gutterClick", cm, line, gutter, e);
        break;
      }
    }
    return true;
  }

  // Kludge to work around strange IE behavior where it'll sometimes
  // re-fire a series of drag-related events right after the drop (#1551)
  var lastDrop = 0;

  function onDrop(e) {
    var cm = this;
    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
      return;
    e_preventDefault(e);
    if (ie) lastDrop = +new Date;
    var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
    if (!pos || isReadOnly(cm)) return;
    if (files && files.length && window.FileReader && window.File) {
      var n = files.length, text = Array(n), read = 0;
      var loadFile = function(file, i) {
        var reader = new FileReader;
        reader.onload = function() {
          text[i] = reader.result;
          if (++read == n) {
            pos = clipPos(cm.doc, pos);
            makeChange(cm.doc, {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"}, "around");
          }
        };
        reader.readAsText(file);
      };
      for (var i = 0; i < n; ++i) loadFile(files[i], i);
    } else {
      // Don't do a replace if the drop happened inside of the selected text.
      if (cm.state.draggingText && !(posLess(pos, cm.doc.sel.from) || posLess(cm.doc.sel.to, pos))) {
        cm.state.draggingText(e);
        // Ensure the editor is re-focused
        setTimeout(bind(focusInput, cm), 20);
        return;
      }
      try {
        var text = e.dataTransfer.getData("Text");
        if (text) {
          var curFrom = cm.doc.sel.from, curTo = cm.doc.sel.to;
          setSelection(cm.doc, pos, pos);
          if (cm.state.draggingText) replaceRange(cm.doc, "", curFrom, curTo, "paste");
          cm.replaceSelection(text, null, "paste");
          focusInput(cm);
          onFocus(cm);
        }
      }
      catch(e){}
    }
  }

  function onDragStart(cm, e) {
    if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
    if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;

    var txt = cm.getSelection();
    e.dataTransfer.setData("Text", txt);

    // Use dummy image instead of default browsers image.
    // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
    if (e.dataTransfer.setDragImage && !safari) {
      var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
      if (opera) {
        img.width = img.height = 1;
        cm.display.wrapper.appendChild(img);
        // Force a relayout, or Opera won't use our image for some obscure reason
        img._top = img.offsetTop;
      }
      e.dataTransfer.setDragImage(img, 0, 0);
      if (opera) img.parentNode.removeChild(img);
    }
  }

  function setScrollTop(cm, val) {
    if (Math.abs(cm.doc.scrollTop - val) < 2) return;
    cm.doc.scrollTop = val;
    if (!gecko) updateDisplay(cm, [], val);
    if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
    if (cm.display.scrollbarV.scrollTop != val) cm.display.scrollbarV.scrollTop = val;
    if (gecko) updateDisplay(cm, []);
    startWorker(cm, 100);
  }
  function setScrollLeft(cm, val, isScroller) {
    if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
    val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
    cm.doc.scrollLeft = val;
    alignHorizontally(cm);
    if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
    if (cm.display.scrollbarH.scrollLeft != val) cm.display.scrollbarH.scrollLeft = val;
  }

  // Since the delta values reported on mouse wheel events are
  // unstandardized between browsers and even browser versions, and
  // generally horribly unpredictable, this code starts by measuring
  // the scroll effect that the first few mouse wheel events have,
  // and, from that, detects the way it can convert deltas to pixel
  // offsets afterwards.
  //
  // The reason we want to know the amount a wheel event will scroll
  // is that it gives us a chance to update the display before the
  // actual scrolling happens, reducing flickering.

  var wheelSamples = 0, wheelPixelsPerUnit = null;
  // Fill in a browser-detected starting value on browsers where we
  // know one. These don't have to be accurate -- the result of them
  // being wrong would just be a slight flicker on the first wheel
  // scroll (if it is large enough).
  if (ie) wheelPixelsPerUnit = -.53;
  else if (gecko) wheelPixelsPerUnit = 15;
  else if (chrome) wheelPixelsPerUnit = -.7;
  else if (safari) wheelPixelsPerUnit = -1/3;

  function onScrollWheel(cm, e) {
    var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
    if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
    if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
    else if (dy == null) dy = e.wheelDelta;

    var display = cm.display, scroll = display.scroller;
    // Quit if there's nothing to scroll here
    if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
          dy && scroll.scrollHeight > scroll.clientHeight)) return;

    // Webkit browsers on OS X abort momentum scrolls when the target
    // of the scroll event is removed from the scrollable element.
    // This hack (see related code in patchDisplay) makes sure the
    // element is kept around.
    if (dy && mac && webkit) {
      for (var cur = e.target; cur != scroll; cur = cur.parentNode) {
        if (cur.lineObj) {
          cm.display.currentWheelTarget = cur;
          break;
        }
      }
    }

    // On some browsers, horizontal scrolling will cause redraws to
    // happen before the gutter has been realigned, causing it to
    // wriggle around in a most unseemly way. When we have an
    // estimated pixels/delta value, we just handle horizontal
    // scrolling entirely here. It'll be slightly off from native, but
    // better than glitching out.
    if (dx && !gecko && !opera && wheelPixelsPerUnit != null) {
      if (dy)
        setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
      setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
      e_preventDefault(e);
      display.wheelStartX = null; // Abort measurement, if in progress
      return;
    }

    if (dy && wheelPixelsPerUnit != null) {
      var pixels = dy * wheelPixelsPerUnit;
      var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
      if (pixels < 0) top = Math.max(0, top + pixels - 50);
      else bot = Math.min(cm.doc.height, bot + pixels + 50);
      updateDisplay(cm, [], {top: top, bottom: bot});
    }

    if (wheelSamples < 20) {
      if (display.wheelStartX == null) {
        display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
        display.wheelDX = dx; display.wheelDY = dy;
        setTimeout(function() {
          if (display.wheelStartX == null) return;
          var movedX = scroll.scrollLeft - display.wheelStartX;
          var movedY = scroll.scrollTop - display.wheelStartY;
          var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
            (movedX && display.wheelDX && movedX / display.wheelDX);
          display.wheelStartX = display.wheelStartY = null;
          if (!sample) return;
          wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
          ++wheelSamples;
        }, 200);
      } else {
        display.wheelDX += dx; display.wheelDY += dy;
      }
    }
  }

  function doHandleBinding(cm, bound, dropShift) {
    if (typeof bound == "string") {
      bound = commands[bound];
      if (!bound) return false;
    }
    // Ensure previous input has been read, so that the handler sees a
    // consistent view of the document
    if (cm.display.pollingFast && readInput(cm)) cm.display.pollingFast = false;
    var doc = cm.doc, prevShift = doc.sel.shift, done = false;
    try {
      if (isReadOnly(cm)) cm.state.suppressEdits = true;
      if (dropShift) doc.sel.shift = false;
      done = bound(cm) != Pass;
    } finally {
      doc.sel.shift = prevShift;
      cm.state.suppressEdits = false;
    }
    return done;
  }

  function allKeyMaps(cm) {
    var maps = cm.state.keyMaps.slice(0);
    if (cm.options.extraKeys) maps.push(cm.options.extraKeys);
    maps.push(cm.options.keyMap);
    return maps;
  }

  var maybeTransition;
  function handleKeyBinding(cm, e) {
    // Handle auto keymap transitions
    var startMap = getKeyMap(cm.options.keyMap), next = startMap.auto;
    clearTimeout(maybeTransition);
    if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {
      if (getKeyMap(cm.options.keyMap) == startMap) {
        cm.options.keyMap = (next.call ? next.call(null, cm) : next);
        keyMapChanged(cm);
      }
    }, 50);

    var name = keyName(e, true), handled = false;
    if (!name) return false;
    var keymaps = allKeyMaps(cm);

    if (e.shiftKey) {
      // First try to resolve full name (including 'Shift-'). Failing
      // that, see if there is a cursor-motion command (starting with
      // 'go') bound to the keyname without 'Shift-'.
      handled = lookupKey("Shift-" + name, keymaps, function(b) {return doHandleBinding(cm, b, true);})
             || lookupKey(name, keymaps, function(b) {
                  if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
                    return doHandleBinding(cm, b);
                });
    } else {
      handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
    }

    if (handled) {
      e_preventDefault(e);
      restartBlink(cm);
      if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
      signalLater(cm, "keyHandled", cm, name, e);
    }
    return handled;
  }

  function handleCharBinding(cm, e, ch) {
    var handled = lookupKey("'" + ch + "'", allKeyMaps(cm),
                            function(b) { return doHandleBinding(cm, b, true); });
    if (handled) {
      e_preventDefault(e);
      restartBlink(cm);
      signalLater(cm, "keyHandled", cm, "'" + ch + "'", e);
    }
    return handled;
  }

  var lastStoppedKey = null;
  function onKeyDown(e) {
    var cm = this;
    if (!cm.state.focused) onFocus(cm);
    if (ie && e.keyCode == 27) { e.returnValue = false; }
    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
    var code = e.keyCode;
    // IE does strange things with escape.
    cm.doc.sel.shift = code == 16 || e.shiftKey;
    // First give onKeyEvent option a chance to handle this.
    var handled = handleKeyBinding(cm, e);
    if (opera) {
      lastStoppedKey = handled ? code : null;
      // Opera has no cut event... we try to at least catch the key combo
      if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
        cm.replaceSelection("");
    }
  }

  function onKeyPress(e) {
    var cm = this;
    if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
    var keyCode = e.keyCode, charCode = e.charCode;
    if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
    if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(cm, e)) return;
    var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
    if (this.options.electricChars && this.doc.mode.electricChars &&
        this.options.smartIndent && !isReadOnly(this) &&
        this.doc.mode.electricChars.indexOf(ch) > -1)
      setTimeout(operation(cm, function() {indentLine(cm, cm.doc.sel.to.line, "smart");}), 75);
    if (handleCharBinding(cm, e, ch)) return;
    if (ie && !ie_lt9) cm.display.inputHasSelection = null;
    fastPoll(cm);
  }

  function onFocus(cm) {
    if (cm.options.readOnly == "nocursor") return;
    if (!cm.state.focused) {
      signal(cm, "focus", cm);
      cm.state.focused = true;
      if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
        cm.display.wrapper.className += " CodeMirror-focused";
      resetInput(cm, true);
    }
    slowPoll(cm);
    restartBlink(cm);
  }
  function onBlur(cm) {
    if (cm.state.focused) {
      signal(cm, "blur", cm);
      cm.state.focused = false;
      cm.display.wrapper.className = cm.display.wrapper.className.replace(" CodeMirror-focused", "");
    }
    clearInterval(cm.display.blinker);
    setTimeout(function() {if (!cm.state.focused) cm.doc.sel.shift = false;}, 150);
  }

  var detectingSelectAll;
  function onContextMenu(cm, e) {
    var display = cm.display, sel = cm.doc.sel;
    if (eventInWidget(display, e)) return;

    var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
    if (!pos || opera) return; // Opera is difficult.
    if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))
      operation(cm, setSelection)(cm.doc, pos, pos);

    var oldCSS = display.input.style.cssText;
    display.inputDiv.style.position = "absolute";
    display.input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
      "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; outline: none;" +
      "border-width: 0; outline: none; overflow: hidden; opacity: .05; -ms-opacity: .05; filter: alpha(opacity=5);";
    focusInput(cm);
    resetInput(cm, true);
    // Adds "Select all" to context menu in FF
    if (posEq(sel.from, sel.to)) display.input.value = display.prevInput = " ";

    function prepareSelectAllHack() {
      if (display.input.selectionStart != null) {
        var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
        display.prevInput = " ";
        display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
      }
    }
    function rehide() {
      display.inputDiv.style.position = "relative";
      display.input.style.cssText = oldCSS;
      if (ie_lt9) display.scrollbarV.scrollTop = display.scroller.scrollTop = scrollPos;
      slowPoll(cm);

      // Try to detect the user choosing select-all
      if (display.input.selectionStart != null) {
        if (!ie || ie_lt9) prepareSelectAllHack();
        clearTimeout(detectingSelectAll);
        var i = 0, poll = function(){
          if (display.prevInput == " " && display.input.selectionStart == 0)
            operation(cm, commands.selectAll)(cm);
          else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500);
          else resetInput(cm);
        };
        detectingSelectAll = setTimeout(poll, 200);
      }
    }

    if (ie && !ie_lt9) prepareSelectAllHack();
    if (captureMiddleClick) {
      e_stop(e);
      var mouseup = function() {
        off(window, "mouseup", mouseup);
        setTimeout(rehide, 20);
      };
      on(window, "mouseup", mouseup);
    } else {
      setTimeout(rehide, 50);
    }
  }

  // UPDATING

  var changeEnd = CodeMirror.changeEnd = function(change) {
    if (!change.text) return change.to;
    return Pos(change.from.line + change.text.length - 1,
               lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
  };

  // Make sure a position will be valid after the given change.
  function clipPostChange(doc, change, pos) {
    if (!posLess(change.from, pos)) return clipPos(doc, pos);
    var diff = (change.text.length - 1) - (change.to.line - change.from.line);
    if (pos.line > change.to.line + diff) {
      var preLine = pos.line - diff, lastLine = doc.first + doc.size - 1;
      if (preLine > lastLine) return Pos(lastLine, getLine(doc, lastLine).text.length);
      return clipToLen(pos, getLine(doc, preLine).text.length);
    }
    if (pos.line == change.to.line + diff)
      return clipToLen(pos, lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0) +
                       getLine(doc, change.to.line).text.length - change.to.ch);
    var inside = pos.line - change.from.line;
    return clipToLen(pos, change.text[inside].length + (inside ? 0 : change.from.ch));
  }

  // Hint can be null|"end"|"start"|"around"|{anchor,head}
  function computeSelAfterChange(doc, change, hint) {
    if (hint && typeof hint == "object") // Assumed to be {anchor, head} object
      return {anchor: clipPostChange(doc, change, hint.anchor),
              head: clipPostChange(doc, change, hint.head)};

    if (hint == "start") return {anchor: change.from, head: change.from};

    var end = changeEnd(change);
    if (hint == "around") return {anchor: change.from, head: end};
    if (hint == "end") return {anchor: end, head: end};

    // hint is null, leave the selection alone as much as possible
    var adjustPos = function(pos) {
      if (posLess(pos, change.from)) return pos;
      if (!posLess(change.to, pos)) return end;

      var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
      if (pos.line == change.to.line) ch += end.ch - change.to.ch;
      return Pos(line, ch);
    };
    return {anchor: adjustPos(doc.sel.anchor), head: adjustPos(doc.sel.head)};
  }

  function filterChange(doc, change, update) {
    var obj = {
      canceled: false,
      from: change.from,
      to: change.to,
      text: change.text,
      origin: change.origin,
      cancel: function() { this.canceled = true; }
    };
    if (update) obj.update = function(from, to, text, origin) {
      if (from) this.from = clipPos(doc, from);
      if (to) this.to = clipPos(doc, to);
      if (text) this.text = text;
      if (origin !== undefined) this.origin = origin;
    };
    signal(doc, "beforeChange", doc, obj);
    if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);

    if (obj.canceled) return null;
    return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
  }

  // Replace the range from from to to by the strings in replacement.
  // change is a {from, to, text [, origin]} object
  function makeChange(doc, change, selUpdate, ignoreReadOnly) {
    if (doc.cm) {
      if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, selUpdate, ignoreReadOnly);
      if (doc.cm.state.suppressEdits) return;
    }

    if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
      change = filterChange(doc, change, true);
      if (!change) return;
    }

    // Possibly split or suppress the update based on the presence
    // of read-only spans in its range.
    var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
    if (split) {
      for (var i = split.length - 1; i >= 1; --i)
        makeChangeNoReadonly(doc, {from: split[i].from, to: split[i].to, text: [""]});
      if (split.length)
        makeChangeNoReadonly(doc, {from: split[0].from, to: split[0].to, text: change.text}, selUpdate);
    } else {
      makeChangeNoReadonly(doc, change, selUpdate);
    }
  }

  function makeChangeNoReadonly(doc, change, selUpdate) {
    var selAfter = computeSelAfterChange(doc, change, selUpdate);
    addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);

    makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
    var rebased = [];

    linkedDocs(doc, function(doc, sharedHist) {
      if (!sharedHist && indexOf(rebased, doc.history) == -1) {
        rebaseHist(doc.history, change);
        rebased.push(doc.history);
      }
      makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
    });
  }

  function makeChangeFromHistory(doc, type) {
    if (doc.cm && doc.cm.state.suppressEdits) return;

    var hist = doc.history;
    var event = (type == "undo" ? hist.done : hist.undone).pop();
    if (!event) return;

    var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
                anchorAfter: event.anchorBefore, headAfter: event.headBefore,
                generation: hist.generation};
    (type == "undo" ? hist.undone : hist.done).push(anti);
    hist.generation = event.generation || ++hist.maxGeneration;

    var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");

    for (var i = event.changes.length - 1; i >= 0; --i) {
      var change = event.changes[i];
      change.origin = type;
      if (filter && !filterChange(doc, change, false)) {
        (type == "undo" ? hist.done : hist.undone).length = 0;
        return;
      }

      anti.changes.push(historyChangeFromChange(doc, change));

      var after = i ? computeSelAfterChange(doc, change, null)
                    : {anchor: event.anchorBefore, head: event.headBefore};
      makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
      var rebased = [];

      linkedDocs(doc, function(doc, sharedHist) {
        if (!sharedHist && indexOf(rebased, doc.history) == -1) {
          rebaseHist(doc.history, change);
          rebased.push(doc.history);
        }
        makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
      });
    }
  }

  function shiftDoc(doc, distance) {
    function shiftPos(pos) {return Pos(pos.line + distance, pos.ch);}
    doc.first += distance;
    if (doc.cm) regChange(doc.cm, doc.first, doc.first, distance);
    doc.sel.head = shiftPos(doc.sel.head); doc.sel.anchor = shiftPos(doc.sel.anchor);
    doc.sel.from = shiftPos(doc.sel.from); doc.sel.to = shiftPos(doc.sel.to);
  }

  function makeChangeSingleDoc(doc, change, selAfter, spans) {
    if (doc.cm && !doc.cm.curOp)
      return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);

    if (change.to.line < doc.first) {
      shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
      return;
    }
    if (change.from.line > doc.lastLine()) return;

    // Clip the change to the size of this doc
    if (change.from.line < doc.first) {
      var shift = change.text.length - 1 - (doc.first - change.from.line);
      shiftDoc(doc, shift);
      change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
                text: [lst(change.text)], origin: change.origin};
    }
    var last = doc.lastLine();
    if (change.to.line > last) {
      change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
                text: [change.text[0]], origin: change.origin};
    }

    change.removed = getBetween(doc, change.from, change.to);

    if (!selAfter) selAfter = computeSelAfterChange(doc, change, null);
    if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans, selAfter);
    else updateDoc(doc, change, spans, selAfter);
  }

  function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
    var doc = cm.doc, display = cm.display, from = change.from, to = change.to;

    var recomputeMaxLength = false, checkWidthStart = from.line;
    if (!cm.options.lineWrapping) {
      checkWidthStart = lineNo(visualLine(doc, getLine(doc, from.line)));
      doc.iter(checkWidthStart, to.line + 1, function(line) {
        if (line == display.maxLine) {
          recomputeMaxLength = true;
          return true;
        }
      });
    }

    if (!posLess(doc.sel.head, change.from) && !posLess(change.to, doc.sel.head))
      cm.curOp.cursorActivity = true;

    updateDoc(doc, change, spans, selAfter, estimateHeight(cm));

    if (!cm.options.lineWrapping) {
      doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
        var len = lineLength(doc, line);
        if (len > display.maxLineLength) {
          display.maxLine = line;
          display.maxLineLength = len;
          display.maxLineChanged = true;
          recomputeMaxLength = false;
        }
      });
      if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
    }

    // Adjust frontier, schedule worker
    doc.frontier = Math.min(doc.frontier, from.line);
    startWorker(cm, 400);

    var lendiff = change.text.length - (to.line - from.line) - 1;
    // Remember that these lines changed, for updating the display
    regChange(cm, from.line, to.line + 1, lendiff);

    if (hasHandler(cm, "change")) {
      var changeObj = {from: from, to: to,
                       text: change.text,
                       removed: change.removed,
                       origin: change.origin};
      if (cm.curOp.textChanged) {
        for (var cur = cm.curOp.textChanged; cur.next; cur = cur.next) {}
        cur.next = changeObj;
      } else cm.curOp.textChanged = changeObj;
    }
  }

  function replaceRange(doc, code, from, to, origin) {
    if (!to) to = from;
    if (posLess(to, from)) { var tmp = to; to = from; from = tmp; }
    if (typeof code == "string") code = splitLines(code);
    makeChange(doc, {from: from, to: to, text: code, origin: origin}, null);
  }

  // POSITION OBJECT

  function Pos(line, ch) {
    if (!(this instanceof Pos)) return new Pos(line, ch);
    this.line = line; this.ch = ch;
  }
  CodeMirror.Pos = Pos;

  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}
  function copyPos(x) {return Pos(x.line, x.ch);}

  // SELECTION

  function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
  function clipPos(doc, pos) {
    if (pos.line < doc.first) return Pos(doc.first, 0);
    var last = doc.first + doc.size - 1;
    if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
    return clipToLen(pos, getLine(doc, pos.line).text.length);
  }
  function clipToLen(pos, linelen) {
    var ch = pos.ch;
    if (ch == null || ch > linelen) return Pos(pos.line, linelen);
    else if (ch < 0) return Pos(pos.line, 0);
    else return pos;
  }
  function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}

  // If shift is held, this will move the selection anchor. Otherwise,
  // it'll set the whole selection.
  function extendSelection(doc, pos, other, bias) {
    if (doc.sel.shift || doc.sel.extend) {
      var anchor = doc.sel.anchor;
      if (other) {
        var posBefore = posLess(pos, anchor);
        if (posBefore != posLess(other, anchor)) {
          anchor = pos;
          pos = other;
        } else if (posBefore != posLess(pos, other)) {
          pos = other;
        }
      }
      setSelection(doc, anchor, pos, bias);
    } else {
      setSelection(doc, pos, other || pos, bias);
    }
    if (doc.cm) doc.cm.curOp.userSelChange = true;
  }

  function filterSelectionChange(doc, anchor, head) {
    var obj = {anchor: anchor, head: head};
    signal(doc, "beforeSelectionChange", doc, obj);
    if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
    obj.anchor = clipPos(doc, obj.anchor); obj.head = clipPos(doc, obj.head);
    return obj;
  }

  // Update the selection. Last two args are only used by
  // updateDoc, since they have to be expressed in the line
  // numbers before the update.
  function setSelection(doc, anchor, head, bias, checkAtomic) {
    if (!checkAtomic && hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) {
      var filtered = filterSelectionChange(doc, anchor, head);
      head = filtered.head;
      anchor = filtered.anchor;
    }

    var sel = doc.sel;
    sel.goalColumn = null;
    // Skip over atomic spans.
    if (checkAtomic || !posEq(anchor, sel.anchor))
      anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
    if (checkAtomic || !posEq(head, sel.head))
      head = skipAtomic(doc, head, bias, checkAtomic != "push");

    if (posEq(sel.anchor, anchor) && posEq(sel.head, head)) return;

    sel.anchor = anchor; sel.head = head;
    var inv = posLess(head, anchor);
    sel.from = inv ? head : anchor;
    sel.to = inv ? anchor : head;

    if (doc.cm)
      doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged =
        doc.cm.curOp.cursorActivity = true;

    signalLater(doc, "cursorActivity", doc);
  }

  function reCheckSelection(cm) {
    setSelection(cm.doc, cm.doc.sel.from, cm.doc.sel.to, null, "push");
  }

  function skipAtomic(doc, pos, bias, mayClear) {
    var flipped = false, curPos = pos;
    var dir = bias || 1;
    doc.cantEdit = false;
    search: for (;;) {
      var line = getLine(doc, curPos.line);
      if (line.markedSpans) {
        for (var i = 0; i < line.markedSpans.length; ++i) {
          var sp = line.markedSpans[i], m = sp.marker;
          if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
              (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
            if (mayClear) {
              signal(m, "beforeCursorEnter");
              if (m.explicitlyCleared) {
                if (!line.markedSpans) break;
                else {--i; continue;}
              }
            }
            if (!m.atomic) continue;
            var newPos = m.find()[dir < 0 ? "from" : "to"];
            if (posEq(newPos, curPos)) {
              newPos.ch += dir;
              if (newPos.ch < 0) {
                if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
                else newPos = null;
              } else if (newPos.ch > line.text.length) {
                if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
                else newPos = null;
              }
              if (!newPos) {
                if (flipped) {
                  // Driven in a corner -- no valid cursor position found at all
                  // -- try again *with* clearing, if we didn't already
                  if (!mayClear) return skipAtomic(doc, pos, bias, true);
                  // Otherwise, turn off editing until further notice, and return the start of the doc
                  doc.cantEdit = true;
                  return Pos(doc.first, 0);
                }
                flipped = true; newPos = pos; dir = -dir;
              }
            }
            curPos = newPos;
            continue search;
          }
        }
      }
      return curPos;
    }
  }

  // SCROLLING

  function scrollCursorIntoView(cm) {
    var coords = scrollPosIntoView(cm, cm.doc.sel.head, cm.options.cursorScrollMargin);
    if (!cm.state.focused) return;
    var display = cm.display, box = getRect(display.sizer), doScroll = null;
    if (coords.top + box.top < 0) doScroll = true;
    else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
    if (doScroll != null && !phantom) {
      var hidden = display.cursor.style.display == "none";
      if (hidden) {
        display.cursor.style.display = "";
        display.cursor.style.left = coords.left + "px";
        display.cursor.style.top = (coords.top - display.viewOffset) + "px";
      }
      display.cursor.scrollIntoView(doScroll);
      if (hidden) display.cursor.style.display = "none";
    }
  }

  function scrollPosIntoView(cm, pos, margin) {
    if (margin == null) margin = 0;
    for (;;) {
      var changed = false, coords = cursorCoords(cm, pos);
      var scrollPos = calculateScrollPos(cm, coords.left, coords.top - margin, coords.left, coords.bottom + margin);
      var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
      if (scrollPos.scrollTop != null) {
        setScrollTop(cm, scrollPos.scrollTop);
        if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
      }
      if (scrollPos.scrollLeft != null) {
        setScrollLeft(cm, scrollPos.scrollLeft);
        if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
      }
      if (!changed) return coords;
    }
  }

  function scrollIntoView(cm, x1, y1, x2, y2) {
    var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
    if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
    if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
  }

  function calculateScrollPos(cm, x1, y1, x2, y2) {
    var display = cm.display, snapMargin = textHeight(cm.display);
    if (y1 < 0) y1 = 0;
    var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
    var docBottom = cm.doc.height + paddingVert(display);
    var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
    if (y1 < screentop) {
      result.scrollTop = atTop ? 0 : y1;
    } else if (y2 > screentop + screen) {
      var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
      if (newTop != screentop) result.scrollTop = newTop;
    }

    var screenw = display.scroller.clientWidth - scrollerCutOff, screenleft = display.scroller.scrollLeft;
    x1 += display.gutters.offsetWidth; x2 += display.gutters.offsetWidth;
    var gutterw = display.gutters.offsetWidth;
    var atLeft = x1 < gutterw + 10;
    if (x1 < screenleft + gutterw || atLeft) {
      if (atLeft) x1 = 0;
      result.scrollLeft = Math.max(0, x1 - 10 - gutterw);
    } else if (x2 > screenw + screenleft - 3) {
      result.scrollLeft = x2 + 10 - screenw;
    }
    return result;
  }

  function updateScrollPos(cm, left, top) {
    cm.curOp.updateScrollPos = {scrollLeft: left == null ? cm.doc.scrollLeft : left,
                                scrollTop: top == null ? cm.doc.scrollTop : top};
  }

  function addToScrollPos(cm, left, top) {
    var pos = cm.curOp.updateScrollPos || (cm.curOp.updateScrollPos = {scrollLeft: cm.doc.scrollLeft, scrollTop: cm.doc.scrollTop});
    var scroll = cm.display.scroller;
    pos.scrollTop = Math.max(0, Math.min(scroll.scrollHeight - scroll.clientHeight, pos.scrollTop + top));
    pos.scrollLeft = Math.max(0, Math.min(scroll.scrollWidth - scroll.clientWidth, pos.scrollLeft + left));
  }

  // API UTILITIES

  function indentLine(cm, n, how, aggressive) {
    var doc = cm.doc;
    if (how == null) how = "add";
    if (how == "smart") {
      if (!cm.doc.mode.indent) how = "prev";
      else var state = getStateBefore(cm, n);
    }

    var tabSize = cm.options.tabSize;
    var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
    var curSpaceString = line.text.match(/^\s*/)[0], indentation;
    if (how == "smart") {
      indentation = cm.doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
      if (indentation == Pass) {
        if (!aggressive) return;
        how = "prev";
      }
    }
    if (how == "prev") {
      if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
      else indentation = 0;
    } else if (how == "add") {
      indentation = curSpace + cm.options.indentUnit;
    } else if (how == "subtract") {
      indentation = curSpace - cm.options.indentUnit;
    } else if (typeof how == "number") {
      indentation = curSpace + how;
    }
    indentation = Math.max(0, indentation);

    var indentString = "", pos = 0;
    if (cm.options.indentWithTabs)
      for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
    if (pos < indentation) indentString += spaceStr(indentation - pos);

    if (indentString != curSpaceString)
      replaceRange(cm.doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
    line.stateAfter = null;
  }

  function changeLine(cm, handle, op) {
    var no = handle, line = handle, doc = cm.doc;
    if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
    else no = lineNo(handle);
    if (no == null) return null;
    if (op(line, no)) regChange(cm, no, no + 1);
    else return null;
    return line;
  }

  function findPosH(doc, pos, dir, unit, visually) {
    var line = pos.line, ch = pos.ch, origDir = dir;
    var lineObj = getLine(doc, line);
    var possible = true;
    function findNextLine() {
      var l = line + dir;
      if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
      line = l;
      return lineObj = getLine(doc, l);
    }
    function moveOnce(boundToLine) {
      var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
      if (next == null) {
        if (!boundToLine && findNextLine()) {
          if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
          else ch = dir < 0 ? lineObj.text.length : 0;
        } else return (possible = false);
      } else ch = next;
      return true;
    }

    if (unit == "char") moveOnce();
    else if (unit == "column") moveOnce(true);
    else if (unit == "word" || unit == "group") {
      var sawType = null, group = unit == "group";
      for (var first = true;; first = false) {
        if (dir < 0 && !moveOnce(!first)) break;
        var cur = lineObj.text.charAt(ch) || "\n";
        var type = isWordChar(cur) ? "w"
          : !group ? null
          : /\s/.test(cur) ? null
          : "p";
        if (sawType && sawType != type) {
          if (dir < 0) {dir = 1; moveOnce();}
          break;
        }
        if (type) sawType = type;
        if (dir > 0 && !moveOnce(!first)) break;
      }
    }
    var result = skipAtomic(doc, Pos(line, ch), origDir, true);
    if (!possible) result.hitSide = true;
    return result;
  }

  function findPosV(cm, pos, dir, unit) {
    var doc = cm.doc, x = pos.left, y;
    if (unit == "page") {
      var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
      y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
    } else if (unit == "line") {
      y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
    }
    for (;;) {
      var target = coordsChar(cm, x, y);
      if (!target.outside) break;
      if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
      y += dir * 5;
    }
    return target;
  }

  function findWordAt(line, pos) {
    var start = pos.ch, end = pos.ch;
    if (line) {
      if (pos.xRel < 0 || end == line.length) --start; else ++end;
      var startChar = line.charAt(start);
      var check = isWordChar(startChar) ? isWordChar
        : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
        : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
      while (start > 0 && check(line.charAt(start - 1))) --start;
      while (end < line.length && check(line.charAt(end))) ++end;
    }
    return {from: Pos(pos.line, start), to: Pos(pos.line, end)};
  }

  function selectLine(cm, line) {
    extendSelection(cm.doc, Pos(line, 0), clipPos(cm.doc, Pos(line + 1, 0)));
  }

  // PROTOTYPE

  // The publicly visible API. Note that operation(null, f) means
  // 'wrap f in an operation, performed on its `this` parameter'

  CodeMirror.prototype = {
    constructor: CodeMirror,
    focus: function(){window.focus(); focusInput(this); onFocus(this); fastPoll(this);},

    setOption: function(option, value) {
      var options = this.options, old = options[option];
      if (options[option] == value && option != "mode") return;
      options[option] = value;
      if (optionHandlers.hasOwnProperty(option))
        operation(this, optionHandlers[option])(this, value, old);
    },

    getOption: function(option) {return this.options[option];},
    getDoc: function() {return this.doc;},

    addKeyMap: function(map, bottom) {
      this.state.keyMaps[bottom ? "push" : "unshift"](map);
    },
    removeKeyMap: function(map) {
      var maps = this.state.keyMaps;
      for (var i = 0; i < maps.length; ++i)
        if ((typeof map == "string" ? maps[i].name : maps[i]) == map) {
          maps.splice(i, 1);
          return true;
        }
    },

    addOverlay: operation(null, function(spec, options) {
      var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
      if (mode.startState) throw new Error("Overlays may not be stateful.");
      this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
      this.state.modeGen++;
      regChange(this);
    }),
    removeOverlay: operation(null, function(spec) {
      var overlays = this.state.overlays;
      for (var i = 0; i < overlays.length; ++i) {
        var cur = overlays[i].modeSpec;
        if (cur == spec || typeof spec == "string" && cur.name == spec) {
          overlays.splice(i, 1);
          this.state.modeGen++;
          regChange(this);
          return;
        }
      }
    }),

    indentLine: operation(null, function(n, dir, aggressive) {
      if (typeof dir != "string" && typeof dir != "number") {
        if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
        else dir = dir ? "add" : "subtract";
      }
      if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
    }),
    indentSelection: operation(null, function(how) {
      var sel = this.doc.sel;
      if (posEq(sel.from, sel.to)) return indentLine(this, sel.from.line, how);
      var e = sel.to.line - (sel.to.ch ? 0 : 1);
      for (var i = sel.from.line; i <= e; ++i) indentLine(this, i, how);
    }),

    // Fetch the parser token for a given character. Useful for hacks
    // that want to inspect the mode state (say, for completion).
    getTokenAt: function(pos, precise) {
      var doc = this.doc;
      pos = clipPos(doc, pos);
      var state = getStateBefore(this, pos.line, precise), mode = this.doc.mode;
      var line = getLine(doc, pos.line);
      var stream = new StringStream(line.text, this.options.tabSize);
      while (stream.pos < pos.ch && !stream.eol()) {
        stream.start = stream.pos;
        var style = mode.token(stream, state);
      }
      return {start: stream.start,
              end: stream.pos,
              string: stream.current(),
              className: style || null, // Deprecated, use 'type' instead
              type: style || null,
              state: state};
    },

    getTokenTypeAt: function(pos) {
      pos = clipPos(this.doc, pos);
      var styles = getLineStyles(this, getLine(this.doc, pos.line));
      var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
      for (;;) {
        var mid = (before + after) >> 1;
        if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
        else if (styles[mid * 2 + 1] < ch) before = mid + 1;
        else return styles[mid * 2 + 2];
      }
    },

    getStateAfter: function(line, precise) {
      var doc = this.doc;
      line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
      return getStateBefore(this, line + 1, precise);
    },

    cursorCoords: function(start, mode) {
      var pos, sel = this.doc.sel;
      if (start == null) pos = sel.head;
      else if (typeof start == "object") pos = clipPos(this.doc, start);
      else pos = start ? sel.from : sel.to;
      return cursorCoords(this, pos, mode || "page");
    },

    charCoords: function(pos, mode) {
      return charCoords(this, clipPos(this.doc, pos), mode || "page");
    },

    coordsChar: function(coords, mode) {
      coords = fromCoordSystem(this, coords, mode || "page");
      return coordsChar(this, coords.left, coords.top);
    },

    lineAtHeight: function(height, mode) {
      height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
      return lineAtHeight(this.doc, height + this.display.viewOffset);
    },
    heightAtLine: function(line, mode) {
      var end = false, last = this.doc.first + this.doc.size - 1;
      if (line < this.doc.first) line = this.doc.first;
      else if (line > last) { line = last; end = true; }
      var lineObj = getLine(this.doc, line);
      return intoCoordSystem(this, getLine(this.doc, line), {top: 0, left: 0}, mode || "page").top +
        (end ? lineObj.height : 0);
    },

    defaultTextHeight: function() { return textHeight(this.display); },
    defaultCharWidth: function() { return charWidth(this.display); },

    setGutterMarker: operation(null, function(line, gutterID, value) {
      return changeLine(this, line, function(line) {
        var markers = line.gutterMarkers || (line.gutterMarkers = {});
        markers[gutterID] = value;
        if (!value && isEmpty(markers)) line.gutterMarkers = null;
        return true;
      });
    }),

    clearGutter: operation(null, function(gutterID) {
      var cm = this, doc = cm.doc, i = doc.first;
      doc.iter(function(line) {
        if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
          line.gutterMarkers[gutterID] = null;
          regChange(cm, i, i + 1);
          if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
        }
        ++i;
      });
    }),

    addLineClass: operation(null, function(handle, where, cls) {
      return changeLine(this, handle, function(line) {
        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
        if (!line[prop]) line[prop] = cls;
        else if (new RegExp("(?:^|\\s)" + cls + "(?:$|\\s)").test(line[prop])) return false;
        else line[prop] += " " + cls;
        return true;
      });
    }),

    removeLineClass: operation(null, function(handle, where, cls) {
      return changeLine(this, handle, function(line) {
        var prop = where == "text" ? "textClass" : where == "background" ? "bgClass" : "wrapClass";
        var cur = line[prop];
        if (!cur) return false;
        else if (cls == null) line[prop] = null;
        else {
          var found = cur.match(new RegExp("(?:^|\\s+)" + cls + "(?:$|\\s+)"));
          if (!found) return false;
          var end = found.index + found[0].length;
          line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
        }
        return true;
      });
    }),

    addLineWidget: operation(null, function(handle, node, options) {
      return addLineWidget(this, handle, node, options);
    }),

    removeLineWidget: function(widget) { widget.clear(); },

    lineInfo: function(line) {
      if (typeof line == "number") {
        if (!isLine(this.doc, line)) return null;
        var n = line;
        line = getLine(this.doc, line);
        if (!line) return null;
      } else {
        var n = lineNo(line);
        if (n == null) return null;
      }
      return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
              textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
              widgets: line.widgets};
    },

    getViewport: function() { return {from: this.display.showingFrom, to: this.display.showingTo};},

    addWidget: function(pos, node, scroll, vert, horiz) {
      var display = this.display;
      pos = cursorCoords(this, clipPos(this.doc, pos));
      var top = pos.bottom, left = pos.left;
      node.style.position = "absolute";
      display.sizer.appendChild(node);
      if (vert == "over") {
        top = pos.top;
      } else if (vert == "above" || vert == "near") {
        var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
        hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
        // Default to positioning above (if specified and possible); otherwise default to positioning below
        if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
          top = pos.top - node.offsetHeight;
        else if (pos.bottom + node.offsetHeight <= vspace)
          top = pos.bottom;
        if (left + node.offsetWidth > hspace)
          left = hspace - node.offsetWidth;
      }
      node.style.top = top + "px";
      node.style.left = node.style.right = "";
      if (horiz == "right") {
        left = display.sizer.clientWidth - node.offsetWidth;
        node.style.right = "0px";
      } else {
        if (horiz == "left") left = 0;
        else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
        node.style.left = left + "px";
      }
      if (scroll)
        scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
    },

    triggerOnKeyDown: operation(null, onKeyDown),

    execCommand: function(cmd) {return commands[cmd](this);},

    findPosH: function(from, amount, unit, visually) {
      var dir = 1;
      if (amount < 0) { dir = -1; amount = -amount; }
      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
        cur = findPosH(this.doc, cur, dir, unit, visually);
        if (cur.hitSide) break;
      }
      return cur;
    },

    moveH: operation(null, function(dir, unit) {
      var sel = this.doc.sel, pos;
      if (sel.shift || sel.extend || posEq(sel.from, sel.to))
        pos = findPosH(this.doc, sel.head, dir, unit, this.options.rtlMoveVisually);
      else
        pos = dir < 0 ? sel.from : sel.to;
      extendSelection(this.doc, pos, pos, dir);
    }),

    deleteH: operation(null, function(dir, unit) {
      var sel = this.doc.sel;
      if (!posEq(sel.from, sel.to)) replaceRange(this.doc, "", sel.from, sel.to, "+delete");
      else replaceRange(this.doc, "", sel.from, findPosH(this.doc, sel.head, dir, unit, false), "+delete");
      this.curOp.userSelChange = true;
    }),

    findPosV: function(from, amount, unit, goalColumn) {
      var dir = 1, x = goalColumn;
      if (amount < 0) { dir = -1; amount = -amount; }
      for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
        var coords = cursorCoords(this, cur, "div");
        if (x == null) x = coords.left;
        else coords.left = x;
        cur = findPosV(this, coords, dir, unit);
        if (cur.hitSide) break;
      }
      return cur;
    },

    moveV: operation(null, function(dir, unit) {
      var sel = this.doc.sel;
      var pos = cursorCoords(this, sel.head, "div");
      if (sel.goalColumn != null) pos.left = sel.goalColumn;
      var target = findPosV(this, pos, dir, unit);

      if (unit == "page") addToScrollPos(this, 0, charCoords(this, target, "div").top - pos.top);
      extendSelection(this.doc, target, target, dir);
      sel.goalColumn = pos.left;
    }),

    toggleOverwrite: function(value) {
      if (value != null && value == this.state.overwrite) return;
      if (this.state.overwrite = !this.state.overwrite)
        this.display.cursor.className += " CodeMirror-overwrite";
      else
        this.display.cursor.className = this.display.cursor.className.replace(" CodeMirror-overwrite", "");
    },
    hasFocus: function() { return this.state.focused; },

    scrollTo: operation(null, function(x, y) {
      updateScrollPos(this, x, y);
    }),
    getScrollInfo: function() {
      var scroller = this.display.scroller, co = scrollerCutOff;
      return {left: scroller.scrollLeft, top: scroller.scrollTop,
              height: scroller.scrollHeight - co, width: scroller.scrollWidth - co,
              clientHeight: scroller.clientHeight - co, clientWidth: scroller.clientWidth - co};
    },

    scrollIntoView: operation(null, function(pos, margin) {
      if (typeof pos == "number") pos = Pos(pos, 0);
      if (!margin) margin = 0;
      var coords = pos;

      if (!pos || pos.line != null) {
        this.curOp.scrollToPos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
        this.curOp.scrollToPosMargin = margin;
        coords = cursorCoords(this, this.curOp.scrollToPos);
      }
      var sPos = calculateScrollPos(this, coords.left, coords.top - margin, coords.right, coords.bottom + margin);
      updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
    }),

    setSize: function(width, height) {
      function interpret(val) {
        return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
      }
      if (width != null) this.display.wrapper.style.width = interpret(width);
      if (height != null) this.display.wrapper.style.height = interpret(height);
      this.refresh();
    },

    on: function(type, f) {on(this, type, f);},
    off: function(type, f) {off(this, type, f);},

    operation: function(f){return runInOp(this, f);},

    refresh: operation(null, function() {
      clearCaches(this);
      updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
      regChange(this);
    }),

    swapDoc: operation(null, function(doc) {
      var old = this.doc;
      old.cm = null;
      attachDoc(this, doc);
      clearCaches(this);
      resetInput(this, true);
      updateScrollPos(this, doc.scrollLeft, doc.scrollTop);
      return old;
    }),

    getInputField: function(){return this.display.input;},
    getWrapperElement: function(){return this.display.wrapper;},
    getScrollerElement: function(){return this.display.scroller;},
    getGutterElement: function(){return this.display.gutters;}
  };

  // OPTION DEFAULTS

  var optionHandlers = CodeMirror.optionHandlers = {};

  // The default configuration options.
  var defaults = CodeMirror.defaults = {};

  function option(name, deflt, handle, notOnInit) {
    CodeMirror.defaults[name] = deflt;
    if (handle) optionHandlers[name] =
      notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
  }

  var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};

  // These two are, on init, called from the constructor because they
  // have to be initialized before the editor can start at all.
  option("value", "", function(cm, val) {
    cm.setValue(val);
  }, true);
  option("mode", null, function(cm, val) {
    cm.doc.modeOption = val;
    loadMode(cm);
  }, true);

  option("indentUnit", 2, loadMode, true);
  option("indentWithTabs", false);
  option("smartIndent", true);
  option("tabSize", 4, function(cm) {
    loadMode(cm);
    clearCaches(cm);
    regChange(cm);
  }, true);
  option("electricChars", true);
  option("rtlMoveVisually", !windows);

  option("theme", "default", function(cm) {
    themeChanged(cm);
    guttersChanged(cm);
  }, true);
  option("keyMap", "default", keyMapChanged);
  option("extraKeys", null);

  option("onKeyEvent", null);
  option("onDragEvent", null);

  option("lineWrapping", false, wrappingChanged, true);
  option("gutters", [], function(cm) {
    setGuttersForLineNumbers(cm.options);
    guttersChanged(cm);
  }, true);
  option("fixedGutter", true, function(cm, val) {
    cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
    cm.refresh();
  }, true);
  option("coverGutterNextToScrollbar", false, updateScrollbars, true);
  option("lineNumbers", false, function(cm) {
    setGuttersForLineNumbers(cm.options);
    guttersChanged(cm);
  }, true);
  option("firstLineNumber", 1, guttersChanged, true);
  option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
  option("showCursorWhenSelecting", false, updateSelection, true);

  option("readOnly", false, function(cm, val) {
    if (val == "nocursor") {onBlur(cm); cm.display.input.blur();}
    else if (!val) resetInput(cm, true);
  });
  option("dragDrop", true);

  option("cursorBlinkRate", 530);
  option("cursorScrollMargin", 0);
  option("cursorHeight", 1);
  option("workTime", 100);
  option("workDelay", 100);
  option("flattenSpans", true);
  option("pollInterval", 100);
  option("undoDepth", 40, function(cm, val){cm.doc.history.undoDepth = val;});
  option("historyEventDelay", 500);
  option("viewportMargin", 10, function(cm){cm.refresh();}, true);
  option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
  option("moveInputWithCursor", true, function(cm, val) {
    if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
  });

  option("tabindex", null, function(cm, val) {
    cm.display.input.tabIndex = val || "";
  });
  option("autofocus", null);

  // MODE DEFINITION AND QUERYING

  // Known modes, by name and by MIME
  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};

  CodeMirror.defineMode = function(name, mode) {
    if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
    if (arguments.length > 2) {
      mode.dependencies = [];
      for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
    }
    modes[name] = mode;
  };

  CodeMirror.defineMIME = function(mime, spec) {
    mimeModes[mime] = spec;
  };

  CodeMirror.resolveMode = function(spec) {
    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
      spec = mimeModes[spec];
    } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
      var found = mimeModes[spec.name];
      spec = createObj(found, spec);
      spec.name = found.name;
    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
      return CodeMirror.resolveMode("application/xml");
    }
    if (typeof spec == "string") return {name: spec};
    else return spec || {name: "null"};
  };

  CodeMirror.getMode = function(options, spec) {
    spec = CodeMirror.resolveMode(spec);
    var mfactory = modes[spec.name];
    if (!mfactory) return CodeMirror.getMode(options, "text/plain");
    var modeObj = mfactory(options, spec);
    if (modeExtensions.hasOwnProperty(spec.name)) {
      var exts = modeExtensions[spec.name];
      for (var prop in exts) {
        if (!exts.hasOwnProperty(prop)) continue;
        if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
        modeObj[prop] = exts[prop];
      }
    }
    modeObj.name = spec.name;
    return modeObj;
  };

  CodeMirror.defineMode("null", function() {
    return {token: function(stream) {stream.skipToEnd();}};
  });
  CodeMirror.defineMIME("text/plain", "null");

  var modeExtensions = CodeMirror.modeExtensions = {};
  CodeMirror.extendMode = function(mode, properties) {
    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
    copyObj(properties, exts);
  };

  // EXTENSIONS

  CodeMirror.defineExtension = function(name, func) {
    CodeMirror.prototype[name] = func;
  };
  CodeMirror.defineDocExtension = function(name, func) {
    Doc.prototype[name] = func;
  };
  CodeMirror.defineOption = option;

  var initHooks = [];
  CodeMirror.defineInitHook = function(f) {initHooks.push(f);};

  // MODE STATE HANDLING

  // Utility functions for working with state. Exported because modes
  // sometimes need to do this.
  function copyState(mode, state) {
    if (state === true) return state;
    if (mode.copyState) return mode.copyState(state);
    var nstate = {};
    for (var n in state) {
      var val = state[n];
      if (val instanceof Array) val = val.concat([]);
      nstate[n] = val;
    }
    return nstate;
  }
  CodeMirror.copyState = copyState;

  function startState(mode, a1, a2) {
    return mode.startState ? mode.startState(a1, a2) : true;
  }
  CodeMirror.startState = startState;

  CodeMirror.innerMode = function(mode, state) {
    while (mode.innerMode) {
      var info = mode.innerMode(state);
      state = info.state;
      mode = info.mode;
    }
    return info || {mode: mode, state: state};
  };

  // STANDARD COMMANDS

  var commands = CodeMirror.commands = {
    selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()));},
    killLine: function(cm) {
      var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);
      if (!sel && cm.getLine(from.line).length == from.ch)
        cm.replaceRange("", from, Pos(from.line + 1, 0), "+delete");
      else cm.replaceRange("", from, sel ? to : Pos(from.line), "+delete");
    },
    deleteLine: function(cm) {
      var l = cm.getCursor().line;
      cm.replaceRange("", Pos(l, 0), Pos(l), "+delete");
    },
    delLineLeft: function(cm) {
      var cur = cm.getCursor();
      cm.replaceRange("", Pos(cur.line, 0), cur, "+delete");
    },
    undo: function(cm) {cm.undo();},
    redo: function(cm) {cm.redo();},
    goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
    goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
    goLineStart: function(cm) {
      cm.extendSelection(lineStart(cm, cm.getCursor().line));
    },
    goLineStartSmart: function(cm) {
      var cur = cm.getCursor(), start = lineStart(cm, cur.line);
      var line = cm.getLineHandle(start.line);
      var order = getOrder(line);
      if (!order || order[0].level == 0) {
        var firstNonWS = Math.max(0, line.text.search(/\S/));
        var inWS = cur.line == start.line && cur.ch <= firstNonWS && cur.ch;
        cm.extendSelection(Pos(start.line, inWS ? 0 : firstNonWS));
      } else cm.extendSelection(start);
    },
    goLineEnd: function(cm) {
      cm.extendSelection(lineEnd(cm, cm.getCursor().line));
    },
    goLineRight: function(cm) {
      var top = cm.charCoords(cm.getCursor(), "div").top + 5;
      cm.extendSelection(cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"));
    },
    goLineLeft: function(cm) {
      var top = cm.charCoords(cm.getCursor(), "div").top + 5;
      cm.extendSelection(cm.coordsChar({left: 0, top: top}, "div"));
    },
    goLineUp: function(cm) {cm.moveV(-1, "line");},
    goLineDown: function(cm) {cm.moveV(1, "line");},
    goPageUp: function(cm) {cm.moveV(-1, "page");},
    goPageDown: function(cm) {cm.moveV(1, "page");},
    goCharLeft: function(cm) {cm.moveH(-1, "char");},
    goCharRight: function(cm) {cm.moveH(1, "char");},
    goColumnLeft: function(cm) {cm.moveH(-1, "column");},
    goColumnRight: function(cm) {cm.moveH(1, "column");},
    goWordLeft: function(cm) {cm.moveH(-1, "word");},
    goGroupRight: function(cm) {cm.moveH(1, "group");},
    goGroupLeft: function(cm) {cm.moveH(-1, "group");},
    goWordRight: function(cm) {cm.moveH(1, "word");},
    delCharBefore: function(cm) {cm.deleteH(-1, "char");},
    delCharAfter: function(cm) {cm.deleteH(1, "char");},
    delWordBefore: function(cm) {cm.deleteH(-1, "word");},
    delWordAfter: function(cm) {cm.deleteH(1, "word");},
    delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
    delGroupAfter: function(cm) {cm.deleteH(1, "group");},
    indentAuto: function(cm) {cm.indentSelection("smart");},
    indentMore: function(cm) {cm.indentSelection("add");},
    indentLess: function(cm) {cm.indentSelection("subtract");},
    insertTab: function(cm) {cm.replaceSelection("\t", "end", "+input");},
    defaultTab: function(cm) {
      if (cm.somethingSelected()) cm.indentSelection("add");
      else cm.replaceSelection("\t", "end", "+input");
    },
    transposeChars: function(cm) {
      var cur = cm.getCursor(), line = cm.getLine(cur.line);
      if (cur.ch > 0 && cur.ch < line.length - 1)
        cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),
                        Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
    },
    newlineAndIndent: function(cm) {
      operation(cm, function() {
        cm.replaceSelection("\n", "end", "+input");
        cm.indentLine(cm.getCursor().line, null, true);
      })();
    },
    toggleOverwrite: function(cm) {cm.toggleOverwrite();}
  };

  // STANDARD KEYMAPS

  var keyMap = CodeMirror.keyMap = {};
  keyMap.basic = {
    "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
    "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
    "Delete": "delCharAfter", "Backspace": "delCharBefore", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
    "Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
  };
  // Note that the save and find-related commands aren't defined by
  // default. Unknown commands are simply ignored.
  keyMap.pcDefault = {
    "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
    "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd",
    "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
    "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
    "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
    "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
    fallthrough: "basic"
  };
  keyMap.macDefault = {
    "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
    "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
    "Alt-Right": "goGroupRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delGroupBefore",
    "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
    "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
    "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delLineLeft",
    fallthrough: ["basic", "emacsy"]
  };
  keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
  keyMap.emacsy = {
    "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
    "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
    "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
    "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
  };

  // KEYMAP DISPATCH

  function getKeyMap(val) {
    if (typeof val == "string") return keyMap[val];
    else return val;
  }

  function lookupKey(name, maps, handle) {
    function lookup(map) {
      map = getKeyMap(map);
      var found = map[name];
      if (found === false) return "stop";
      if (found != null && handle(found)) return true;
      if (map.nofallthrough) return "stop";

      var fallthrough = map.fallthrough;
      if (fallthrough == null) return false;
      if (Object.prototype.toString.call(fallthrough) != "[object Array]")
        return lookup(fallthrough);
      for (var i = 0, e = fallthrough.length; i < e; ++i) {
        var done = lookup(fallthrough[i]);
        if (done) return done;
      }
      return false;
    }

    for (var i = 0; i < maps.length; ++i) {
      var done = lookup(maps[i]);
      if (done) return done != "stop";
    }
  }
  function isModifierKey(event) {
    var name = keyNames[event.keyCode];
    return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
  }
  function keyName(event, noShift) {
    if (opera && event.keyCode == 34 && event["char"]) return false;
    var name = keyNames[event.keyCode];
    if (name == null || event.altGraphKey) return false;
    if (event.altKey) name = "Alt-" + name;
    if (flipCtrlCmd ? event.metaKey : event.ctrlKey) name = "Ctrl-" + name;
    if (flipCtrlCmd ? event.ctrlKey : event.metaKey) name = "Cmd-" + name;
    if (!noShift && event.shiftKey) name = "Shift-" + name;
    return name;
  }
  CodeMirror.lookupKey = lookupKey;
  CodeMirror.isModifierKey = isModifierKey;
  CodeMirror.keyName = keyName;

  // FROMTEXTAREA

  CodeMirror.fromTextArea = function(textarea, options) {
    if (!options) options = {};
    options.value = textarea.value;
    if (!options.tabindex && textarea.tabindex)
      options.tabindex = textarea.tabindex;
    if (!options.placeholder && textarea.placeholder)
      options.placeholder = textarea.placeholder;
    // Set autofocus to true if this textarea is focused, or if it has
    // autofocus and no other element is focused.
    if (options.autofocus == null) {
      var hasFocus = document.body;
      // doc.activeElement occasionally throws on IE
      try { hasFocus = document.activeElement; } catch(e) {}
      options.autofocus = hasFocus == textarea ||
        textarea.getAttribute("autofocus") != null && hasFocus == document.body;
    }

    function save() {textarea.value = cm.getValue();}
    if (textarea.form) {
      on(textarea.form, "submit", save);
      // Deplorable hack to make the submit method do the right thing.
      if (!options.leaveSubmitMethodAlone) {
        var form = textarea.form, realSubmit = form.submit;
        try {
          var wrappedSubmit = form.submit = function() {
            save();
            form.submit = realSubmit;
            form.submit();
            form.submit = wrappedSubmit;
          };
        } catch(e) {}
      }
    }

    textarea.style.display = "none";
    var cm = CodeMirror(function(node) {
      textarea.parentNode.insertBefore(node, textarea.nextSibling);
    }, options);
    cm.save = save;
    cm.getTextArea = function() { return textarea; };
    cm.toTextArea = function() {
      save();
      textarea.parentNode.removeChild(cm.getWrapperElement());
      textarea.style.display = "";
      if (textarea.form) {
        off(textarea.form, "submit", save);
        if (typeof textarea.form.submit == "function")
          textarea.form.submit = realSubmit;
      }
    };
    return cm;
  };

  // STRING STREAM

  // Fed to the mode parsers, provides helper functions to make
  // parsers more succinct.

  // The character stream used by a mode's parser.
  function StringStream(string, tabSize) {
    this.pos = this.start = 0;
    this.string = string;
    this.tabSize = tabSize || 8;
    this.lastColumnPos = this.lastColumnValue = 0;
  }

  StringStream.prototype = {
    eol: function() {return this.pos >= this.string.length;},
    sol: function() {return this.pos == 0;},
    peek: function() {return this.string.charAt(this.pos) || undefined;},
    next: function() {
      if (this.pos < this.string.length)
        return this.string.charAt(this.pos++);
    },
    eat: function(match) {
      var ch = this.string.charAt(this.pos);
      if (typeof match == "string") var ok = ch == match;
      else var ok = ch && (match.test ? match.test(ch) : match(ch));
      if (ok) {++this.pos; return ch;}
    },
    eatWhile: function(match) {
      var start = this.pos;
      while (this.eat(match)){}
      return this.pos > start;
    },
    eatSpace: function() {
      var start = this.pos;
      while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
      return this.pos > start;
    },
    skipToEnd: function() {this.pos = this.string.length;},
    skipTo: function(ch) {
      var found = this.string.indexOf(ch, this.pos);
      if (found > -1) {this.pos = found; return true;}
    },
    backUp: function(n) {this.pos -= n;},
    column: function() {
      if (this.lastColumnPos < this.start) {
        this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
        this.lastColumnPos = this.start;
      }
      return this.lastColumnValue;
    },
    indentation: function() {return countColumn(this.string, null, this.tabSize);},
    match: function(pattern, consume, caseInsensitive) {
      if (typeof pattern == "string") {
        var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
        var substr = this.string.substr(this.pos, pattern.length);
        if (cased(substr) == cased(pattern)) {
          if (consume !== false) this.pos += pattern.length;
          return true;
        }
      } else {
        var match = this.string.slice(this.pos).match(pattern);
        if (match && match.index > 0) return null;
        if (match && consume !== false) this.pos += match[0].length;
        return match;
      }
    },
    current: function(){return this.string.slice(this.start, this.pos);}
  };
  CodeMirror.StringStream = StringStream;

  // TEXTMARKERS

  function TextMarker(doc, type) {
    this.lines = [];
    this.type = type;
    this.doc = doc;
  }
  CodeMirror.TextMarker = TextMarker;

  TextMarker.prototype.clear = function() {
    if (this.explicitlyCleared) return;
    var cm = this.doc.cm, withOp = cm && !cm.curOp;
    if (withOp) startOperation(cm);
    var min = null, max = null;
    for (var i = 0; i < this.lines.length; ++i) {
      var line = this.lines[i];
      var span = getMarkedSpanFor(line.markedSpans, this);
      if (span.to != null) max = lineNo(line);
      line.markedSpans = removeMarkedSpan(line.markedSpans, span);
      if (span.from != null)
        min = lineNo(line);
      else if (this.collapsed && !lineIsHidden(this.doc, line) && cm)
        updateLineHeight(line, textHeight(cm.display));
    }
    if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
      var visual = visualLine(cm.doc, this.lines[i]), len = lineLength(cm.doc, visual);
      if (len > cm.display.maxLineLength) {
        cm.display.maxLine = visual;
        cm.display.maxLineLength = len;
        cm.display.maxLineChanged = true;
      }
    }

    if (min != null && cm) regChange(cm, min, max + 1);
    this.lines.length = 0;
    this.explicitlyCleared = true;
    if (this.atomic && this.doc.cantEdit) {
      this.doc.cantEdit = false;
      if (cm) reCheckSelection(cm);
    }
    if (withOp) endOperation(cm);
    signalLater(this, "clear");
  };

  TextMarker.prototype.find = function() {
    var from, to;
    for (var i = 0; i < this.lines.length; ++i) {
      var line = this.lines[i];
      var span = getMarkedSpanFor(line.markedSpans, this);
      if (span.from != null || span.to != null) {
        var found = lineNo(line);
        if (span.from != null) from = Pos(found, span.from);
        if (span.to != null) to = Pos(found, span.to);
      }
    }
    if (this.type == "bookmark") return from;
    return from && {from: from, to: to};
  };

  TextMarker.prototype.changed = function() {
    var pos = this.find(), cm = this.doc.cm;
    if (!pos || !cm) return;
    var line = getLine(this.doc, pos.from.line);
    clearCachedMeasurement(cm, line);
    if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
      for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
        if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
        break;
      }
      runInOp(cm, function() { cm.curOp.selectionChanged = true; });
    }
  };

  TextMarker.prototype.attachLine = function(line) {
    if (!this.lines.length && this.doc.cm) {
      var op = this.doc.cm.curOp;
      if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
        (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
    }
    this.lines.push(line);
  };
  TextMarker.prototype.detachLine = function(line) {
    this.lines.splice(indexOf(this.lines, line), 1);
    if (!this.lines.length && this.doc.cm) {
      var op = this.doc.cm.curOp;
      (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
    }
  };

  function markText(doc, from, to, options, type) {
    if (options && options.shared) return markTextShared(doc, from, to, options, type);
    if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);

    var marker = new TextMarker(doc, type);
    if (type == "range" && !posLess(from, to)) return marker;
    if (options) copyObj(options, marker);
    if (marker.replacedWith) {
      marker.collapsed = true;
      marker.replacedWith = elt("span", [marker.replacedWith], "CodeMirror-widget");
      if (!options.handleMouseEvents) marker.replacedWith.ignoreEvents = true;
    }
    if (marker.collapsed) sawCollapsedSpans = true;

    if (marker.addToHistory)
      addToHistory(doc, {from: from, to: to, origin: "markText"},
                   {head: doc.sel.head, anchor: doc.sel.anchor}, NaN);

    var curLine = from.line, size = 0, collapsedAtStart, collapsedAtEnd, cm = doc.cm, updateMaxLine;
    doc.iter(curLine, to.line + 1, function(line) {
      if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(doc, line) == cm.display.maxLine)
        updateMaxLine = true;
      var span = {from: null, to: null, marker: marker};
      size += line.text.length;
      if (curLine == from.line) {span.from = from.ch; size -= from.ch;}
      if (curLine == to.line) {span.to = to.ch; size -= line.text.length - to.ch;}
      if (marker.collapsed) {
        if (curLine == to.line) collapsedAtEnd = collapsedSpanAt(line, to.ch);
        if (curLine == from.line) collapsedAtStart = collapsedSpanAt(line, from.ch);
        else updateLineHeight(line, 0);
      }
      addMarkedSpan(line, span);
      ++curLine;
    });
    if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
      if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
    });

    if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });

    if (marker.readOnly) {
      sawReadOnlySpans = true;
      if (doc.history.done.length || doc.history.undone.length)
        doc.clearHistory();
    }
    if (marker.collapsed) {
      if (collapsedAtStart != collapsedAtEnd)
        throw new Error("Inserting collapsed marker overlapping an existing one");
      marker.size = size;
      marker.atomic = true;
    }
    if (cm) {
      if (updateMaxLine) cm.curOp.updateMaxLine = true;
      if (marker.className || marker.startStyle || marker.endStyle || marker.collapsed)
        regChange(cm, from.line, to.line + 1);
      if (marker.atomic) reCheckSelection(cm);
    }
    return marker;
  }

  // SHARED TEXTMARKERS

  function SharedTextMarker(markers, primary) {
    this.markers = markers;
    this.primary = primary;
    for (var i = 0, me = this; i < markers.length; ++i) {
      markers[i].parent = this;
      on(markers[i], "clear", function(){me.clear();});
    }
  }
  CodeMirror.SharedTextMarker = SharedTextMarker;

  SharedTextMarker.prototype.clear = function() {
    if (this.explicitlyCleared) return;
    this.explicitlyCleared = true;
    for (var i = 0; i < this.markers.length; ++i)
      this.markers[i].clear();
    signalLater(this, "clear");
  };
  SharedTextMarker.prototype.find = function() {
    return this.primary.find();
  };

  function markTextShared(doc, from, to, options, type) {
    options = copyObj(options);
    options.shared = false;
    var markers = [markText(doc, from, to, options, type)], primary = markers[0];
    var widget = options.replacedWith;
    linkedDocs(doc, function(doc) {
      if (widget) options.replacedWith = widget.cloneNode(true);
      markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
      for (var i = 0; i < doc.linked.length; ++i)
        if (doc.linked[i].isParent) return;
      primary = lst(markers);
    });
    return new SharedTextMarker(markers, primary);
  }

  // TEXTMARKER SPANS

  function getMarkedSpanFor(spans, marker) {
    if (spans) for (var i = 0; i < spans.length; ++i) {
      var span = spans[i];
      if (span.marker == marker) return span;
    }
  }
  function removeMarkedSpan(spans, span) {
    for (var r, i = 0; i < spans.length; ++i)
      if (spans[i] != span) (r || (r = [])).push(spans[i]);
    return r;
  }
  function addMarkedSpan(line, span) {
    line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
    span.marker.attachLine(line);
  }

  function markedSpansBefore(old, startCh, isInsert) {
    if (old) for (var i = 0, nw; i < old.length; ++i) {
      var span = old[i], marker = span.marker;
      var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
      if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
        var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
        (nw || (nw = [])).push({from: span.from,
                                to: endsAfter ? null : span.to,
                                marker: marker});
      }
    }
    return nw;
  }

  function markedSpansAfter(old, endCh, isInsert) {
    if (old) for (var i = 0, nw; i < old.length; ++i) {
      var span = old[i], marker = span.marker;
      var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
      if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
        var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
        (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
                                to: span.to == null ? null : span.to - endCh,
                                marker: marker});
      }
    }
    return nw;
  }

  function stretchSpansOverChange(doc, change) {
    var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
    var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
    if (!oldFirst && !oldLast) return null;

    var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
    // Get the spans that 'stick out' on both sides
    var first = markedSpansBefore(oldFirst, startCh, isInsert);
    var last = markedSpansAfter(oldLast, endCh, isInsert);

    // Next, merge those two ends
    var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
    if (first) {
      // Fix up .to properties of first
      for (var i = 0; i < first.length; ++i) {
        var span = first[i];
        if (span.to == null) {
          var found = getMarkedSpanFor(last, span.marker);
          if (!found) span.to = startCh;
          else if (sameLine) span.to = found.to == null ? null : found.to + offset;
        }
      }
    }
    if (last) {
      // Fix up .from in last (or move them into first in case of sameLine)
      for (var i = 0; i < last.length; ++i) {
        var span = last[i];
        if (span.to != null) span.to += offset;
        if (span.from == null) {
          var found = getMarkedSpanFor(first, span.marker);
          if (!found) {
            span.from = offset;
            if (sameLine) (first || (first = [])).push(span);
          }
        } else {
          span.from += offset;
          if (sameLine) (first || (first = [])).push(span);
        }
      }
    }
    if (sameLine && first) {
      // Make sure we didn't create any zero-length spans
      for (var i = 0; i < first.length; ++i)
        if (first[i].from != null && first[i].from == first[i].to && first[i].marker.type != "bookmark")
          first.splice(i--, 1);
      if (!first.length) first = null;
    }

    var newMarkers = [first];
    if (!sameLine) {
      // Fill gap with whole-line-spans
      var gap = change.text.length - 2, gapMarkers;
      if (gap > 0 && first)
        for (var i = 0; i < first.length; ++i)
          if (first[i].to == null)
            (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker});
      for (var i = 0; i < gap; ++i)
        newMarkers.push(gapMarkers);
      newMarkers.push(last);
    }
    return newMarkers;
  }

  function mergeOldSpans(doc, change) {
    var old = getOldSpans(doc, change);
    var stretched = stretchSpansOverChange(doc, change);
    if (!old) return stretched;
    if (!stretched) return old;

    for (var i = 0; i < old.length; ++i) {
      var oldCur = old[i], stretchCur = stretched[i];
      if (oldCur && stretchCur) {
        spans: for (var j = 0; j < stretchCur.length; ++j) {
          var span = stretchCur[j];
          for (var k = 0; k < oldCur.length; ++k)
            if (oldCur[k].marker == span.marker) continue spans;
          oldCur.push(span);
        }
      } else if (stretchCur) {
        old[i] = stretchCur;
      }
    }
    return old;
  }

  function removeReadOnlyRanges(doc, from, to) {
    var markers = null;
    doc.iter(from.line, to.line + 1, function(line) {
      if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
        var mark = line.markedSpans[i].marker;
        if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
          (markers || (markers = [])).push(mark);
      }
    });
    if (!markers) return null;
    var parts = [{from: from, to: to}];
    for (var i = 0; i < markers.length; ++i) {
      var mk = markers[i], m = mk.find();
      for (var j = 0; j < parts.length; ++j) {
        var p = parts[j];
        if (posLess(p.to, m.from) || posLess(m.to, p.from)) continue;
        var newParts = [j, 1];
        if (posLess(p.from, m.from) || !mk.inclusiveLeft && posEq(p.from, m.from))
          newParts.push({from: p.from, to: m.from});
        if (posLess(m.to, p.to) || !mk.inclusiveRight && posEq(p.to, m.to))
          newParts.push({from: m.to, to: p.to});
        parts.splice.apply(parts, newParts);
        j += newParts.length - 1;
      }
    }
    return parts;
  }

  function collapsedSpanAt(line, ch) {
    var sps = sawCollapsedSpans && line.markedSpans, found;
    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
      sp = sps[i];
      if (!sp.marker.collapsed) continue;
      if ((sp.from == null || sp.from < ch) &&
          (sp.to == null || sp.to > ch) &&
          (!found || found.width < sp.marker.width))
        found = sp.marker;
    }
    return found;
  }
  function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
  function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.text.length + 1); }

  function visualLine(doc, line) {
    var merged;
    while (merged = collapsedSpanAtStart(line))
      line = getLine(doc, merged.find().from.line);
    return line;
  }

  function lineIsHidden(doc, line) {
    var sps = sawCollapsedSpans && line.markedSpans;
    if (sps) for (var sp, i = 0; i < sps.length; ++i) {
      sp = sps[i];
      if (!sp.marker.collapsed) continue;
      if (sp.from == null) return true;
      if (sp.marker.replacedWith) continue;
      if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
        return true;
    }
  }
  function lineIsHiddenInner(doc, line, span) {
    if (span.to == null) {
      var end = span.marker.find().to, endLine = getLine(doc, end.line);
      return lineIsHiddenInner(doc, endLine, getMarkedSpanFor(endLine.markedSpans, span.marker));
    }
    if (span.marker.inclusiveRight && span.to == line.text.length)
      return true;
    for (var sp, i = 0; i < line.markedSpans.length; ++i) {
      sp = line.markedSpans[i];
      if (sp.marker.collapsed && !sp.marker.replacedWith && sp.from == span.to &&
          (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
          lineIsHiddenInner(doc, line, sp)) return true;
    }
  }

  function detachMarkedSpans(line) {
    var spans = line.markedSpans;
    if (!spans) return;
    for (var i = 0; i < spans.length; ++i)
      spans[i].marker.detachLine(line);
    line.markedSpans = null;
  }

  function attachMarkedSpans(line, spans) {
    if (!spans) return;
    for (var i = 0; i < spans.length; ++i)
      spans[i].marker.attachLine(line);
    line.markedSpans = spans;
  }

  // LINE WIDGETS

  var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
    for (var opt in options) if (options.hasOwnProperty(opt))
      this[opt] = options[opt];
    this.cm = cm;
    this.node = node;
  };
  function widgetOperation(f) {
    return function() {
      var withOp = !this.cm.curOp;
      if (withOp) startOperation(this.cm);
      try {var result = f.apply(this, arguments);}
      finally {if (withOp) endOperation(this.cm);}
      return result;
    };
  }
  LineWidget.prototype.clear = widgetOperation(function() {
    var ws = this.line.widgets, no = lineNo(this.line);
    if (no == null || !ws) return;
    for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
    if (!ws.length) this.line.widgets = null;
    updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
    regChange(this.cm, no, no + 1);
  });
  LineWidget.prototype.changed = widgetOperation(function() {
    var oldH = this.height;
    this.height = null;
    var diff = widgetHeight(this) - oldH;
    if (!diff) return;
    updateLineHeight(this.line, this.line.height + diff);
    var no = lineNo(this.line);
    regChange(this.cm, no, no + 1);
  });

  function widgetHeight(widget) {
    if (widget.height != null) return widget.height;
    if (!widget.node.parentNode || widget.node.parentNode.nodeType != 1)
      removeChildrenAndAdd(widget.cm.display.measure, elt("div", [widget.node], null, "position: relative"));
    return widget.height = widget.node.offsetHeight;
  }

  function addLineWidget(cm, handle, node, options) {
    var widget = new LineWidget(cm, node, options);
    if (widget.noHScroll) cm.display.alignWidgets = true;
    changeLine(cm, handle, function(line) {
      (line.widgets || (line.widgets = [])).push(widget);
      widget.line = line;
      if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
        var aboveVisible = heightAtLine(cm, line) < cm.display.scroller.scrollTop;
        updateLineHeight(line, line.height + widgetHeight(widget));
        if (aboveVisible) addToScrollPos(cm, 0, widget.height);
      }
      return true;
    });
    return widget;
  }

  // LINE DATA STRUCTURE

  // Line objects. These hold state related to a line, including
  // highlighting info (the styles array).
  function makeLine(text, markedSpans, estimateHeight) {
    var line = {text: text};
    attachMarkedSpans(line, markedSpans);
    line.height = estimateHeight ? estimateHeight(line) : 1;
    return line;
  }

  function updateLine(line, text, markedSpans, estimateHeight) {
    line.text = text;
    if (line.stateAfter) line.stateAfter = null;
    if (line.styles) line.styles = null;
    if (line.order != null) line.order = null;
    detachMarkedSpans(line);
    attachMarkedSpans(line, markedSpans);
    var estHeight = estimateHeight ? estimateHeight(line) : 1;
    if (estHeight != line.height) updateLineHeight(line, estHeight);
  }

  function cleanUpLine(line) {
    line.parent = null;
    detachMarkedSpans(line);
  }

  // Run the given mode's parser over a line, update the styles
  // ar
Download .txt
gitextract_5ucek8is/

├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── bin/
│   └── ki
├── editor/
│   ├── addon/
│   │   └── runmode.js
│   ├── codemirror.css
│   ├── editor.html
│   ├── index.html
│   ├── mode/
│   │   ├── javascript/
│   │   │   └── javascript.js
│   │   └── runmode.js
│   ├── scripts/
│   │   ├── codemirror.js
│   │   ├── editor.js
│   │   ├── escodegen.js
│   │   ├── escope.js
│   │   ├── estraverse.js
│   │   ├── expander.js
│   │   ├── jquery.js
│   │   ├── ki.js
│   │   ├── ki.sjs
│   │   ├── main.js
│   │   ├── mori.js
│   │   ├── parser.js
│   │   ├── patterns.js
│   │   ├── require.js
│   │   ├── scopedEval.js
│   │   ├── stxcase.js
│   │   ├── sweet.js
│   │   ├── syntax.js
│   │   ├── text.js
│   │   └── underscore.js
│   └── theme/
│       └── sweetprism.css
├── lib/
│   ├── ki.js
│   └── ki_run.js
├── macros/
│   └── index.js
├── package.json
├── src/
│   └── ki.sjs
└── test/
    └── core.js
Download .txt
SYMBOL INDEX (1317 symbols across 18 files)

FILE: Gruntfile.js
  function compileFile (line 40) | function compileFile(fileName, isTest) {

FILE: editor/mode/javascript/javascript.js
  function kw (line 11) | function kw(type) {return {type: type, style: "keyword"};}
  function chain (line 57) | function chain(stream, state, f) {
  function nextUntilUnescaped (line 62) | function nextUntilUnescaped(stream, end) {
  function ret (line 75) | function ret(tp, style, cont) {
  function jsTokenBase (line 80) | function jsTokenBase(stream, state) {
  function jsTokenString (line 129) | function jsTokenString(quote) {
  function jsTokenComment (line 137) | function jsTokenComment(stream, state) {
  function JSLexical (line 153) | function JSLexical(indented, column, type, align, prev, info) {
  function inScope (line 162) | function inScope(state, varname) {
  function parseJS (line 167) | function parseJS(state, style, type, content, stream) {
  function pass (line 191) | function pass() {
  function cont (line 194) | function cont() {
  function register (line 198) | function register(varname) {
  function pushcontext (line 211) | function pushcontext() {
  function popcontext (line 215) | function popcontext() {
  function pushlex (line 219) | function pushlex(type, info) {
  function poplex (line 227) | function poplex() {
  function expect (line 237) | function expect(wanted) {
  function statement (line 245) | function statement(type) {
  function expression (line 263) | function expression(type) {
  function maybeexpression (line 273) | function maybeexpression(type) {
  function maybeoperator (line 278) | function maybeoperator(type, value) {
  function maybelabel (line 286) | function maybelabel(type) {
  function property (line 290) | function property(type) {
  function objprop (line 293) | function objprop(type) {
  function commasep (line 297) | function commasep(what, end) {
  function block (line 308) | function block(type) {
  function maybetype (line 312) | function maybetype(type) {
  function typedef (line 316) | function typedef(type) {
  function vardef1 (line 320) | function vardef1(type, value) {
  function vardef2 (line 327) | function vardef2(type, value) {
  function forspec1 (line 331) | function forspec1(type) {
  function formaybein (line 337) | function formaybein(_type, value) {
  function forspec2 (line 341) | function forspec2(type, value) {
  function forspec3 (line 346) | function forspec3(type) {
  function functiondef (line 349) | function functiondef(type, value) {
  function funarg (line 353) | function funarg(type, value) {

FILE: editor/scripts/codemirror.js
  function CodeMirror (line 42) | function CodeMirror(place, options) {
  function makeDisplay (line 94) | function makeDisplay(place, docStart) {
  function loadMode (line 193) | function loadMode(cm) {
  function wrappingChanged (line 205) | function wrappingChanged(cm) {
  function estimateHeight (line 219) | function estimateHeight(cm) {
  function estimateLineHeights (line 232) | function estimateLineHeights(cm) {
  function keyMapChanged (line 240) | function keyMapChanged(cm) {
  function themeChanged (line 247) | function themeChanged(cm) {
  function guttersChanged (line 253) | function guttersChanged(cm) {
  function updateGutters (line 259) | function updateGutters(cm) {
  function lineLength (line 273) | function lineLength(doc, line) {
  function computeMaxLength (line 291) | function computeMaxLength(cm) {
  function setGuttersForLineNumbers (line 307) | function setGuttersForLineNumbers(options) {
  function updateScrollbars (line 323) | function updateScrollbars(cm) {
  function visibleLines (line 357) | function visibleLines(display, doc, viewPort) {
  function alignHorizontally (line 368) | function alignHorizontally(cm) {
  function maybeUpdateLineNumberWidth (line 380) | function maybeUpdateLineNumberWidth(cm) {
  function lineNumberFor (line 397) | function lineNumberFor(options, i) {
  function compensateForHScroll (line 400) | function compensateForHScroll(display) {
  function updateDisplay (line 406) | function updateDisplay(cm, changes, viewPort) {
  function updateDisplayInner (line 436) | function updateDisplayInner(cm, changes, visible) {
  function updateViewOffset (line 547) | function updateViewOffset(cm) {
  function computeIntact (line 553) | function computeIntact(intact, changes) {
  function getDimensions (line 574) | function getDimensions(cm) {
  function patchDisplay (line 587) | function patchDisplay(cm, from, to, intact, updateNumbersFrom) {
  function buildLineElement (line 654) | function buildLineElement(cm, line, lineNo, dims, reuse) {
  function positionLineWidget (line 731) | function positionLineWidget(widget, node, wrap, dims) {
  function updateSelection (line 751) | function updateSelection(cm) {
  function updateSelectionCursor (line 775) | function updateSelectionCursor(cm) {
  function updateSelectionRange (line 791) | function updateSelectionRange(cm) {
  function restartBlink (line 863) | function restartBlink(cm) {
  function startWorker (line 876) | function startWorker(cm, time) {
  function highlightWorker (line 881) | function highlightWorker(cm) {
  function findStartLine (line 921) | function findStartLine(cm, n, precise) {
  function getStateBefore (line 936) | function getStateBefore(cm, n, precise) {
  function paddingTop (line 953) | function paddingTop(display) {return display.lineSpace.offsetTop;}
  function paddingVert (line 954) | function paddingVert(display) {return display.mover.offsetHeight - displ...
  function paddingLeft (line 955) | function paddingLeft(display) {
  function measureChar (line 960) | function measureChar(cm, line, ch, data, bias) {
  function findCachedMeasurement (line 976) | function findCachedMeasurement(cm, line) {
  function clearCachedMeasurement (line 987) | function clearCachedMeasurement(cm, line) {
  function measureLine (line 992) | function measureLine(cm, line) {
  function measureLineInner (line 1008) | function measureLineInner(cm, line) {
  function measureLineWidth (line 1092) | function measureLineWidth(cm, line) {
  function clearCaches (line 1107) | function clearCaches(cm) {
  function pageScrollX (line 1114) | function pageScrollX() { return window.pageXOffset || (document.document...
  function pageScrollY (line 1115) | function pageScrollY() { return window.pageYOffset || (document.document...
  function intoCoordSystem (line 1118) | function intoCoordSystem(cm, lineObj, rect, context) {
  function fromCoordSystem (line 1140) | function fromCoordSystem(cm, coords, context) {
  function charCoords (line 1157) | function charCoords(cm, pos, context, lineObj, bias) {
  function cursorCoords (line 1162) | function cursorCoords(cm, pos, context, lineObj, measurement) {
  function PosWithInfo (line 1192) | function PosWithInfo(line, ch, outside, xRel) {
  function coordsChar (line 1200) | function coordsChar(cm, x, y) {
  function coordsCharInner (line 1221) | function coordsCharInner(cm, lineObj, lineNo, x, y) {
  function textHeight (line 1263) | function textHeight(display) {
  function charWidth (line 1282) | function charWidth(display) {
  function startOperation (line 1300) | function startOperation(cm) {
  function endOperation (line 1317) | function endOperation(cm) {
  function operation (line 1374) | function operation(cm1, f) {
  function docOperation (line 1383) | function docOperation(f) {
  function runInOp (line 1392) | function runInOp(cm, f) {
  function regChange (line 1400) | function regChange(cm, from, to, lendiff) {
  function slowPoll (line 1408) | function slowPoll(cm) {
  function fastPoll (line 1416) | function fastPoll(cm) {
  function readInput (line 1432) | function readInput(cm) {
  function resetInput (line 1467) | function resetInput(cm, user) {
  function focusInput (line 1484) | function focusInput(cm) {
  function isReadOnly (line 1489) | function isReadOnly(cm) {
  function registerEventHandlers (line 1495) | function registerEventHandlers(cm) {
  function eventInWidget (line 1609) | function eventInWidget(display, e) {
  function posFromMouse (line 1615) | function posFromMouse(cm, e, liberal) {
  function onMouseDown (line 1630) | function onMouseDown(e) {
  function clickInGutter (line 1770) | function clickInGutter(cm, e) {
  function onDrop (line 1799) | function onDrop(e) {
  function onDragStart (line 1844) | function onDragStart(cm, e) {
  function setScrollTop (line 1866) | function setScrollTop(cm, val) {
  function setScrollLeft (line 1875) | function setScrollLeft(cm, val, isScroller) {
  function onScrollWheel (line 1905) | function onScrollWheel(cm, e) {
  function doHandleBinding (line 1973) | function doHandleBinding(cm, bound, dropShift) {
  function allKeyMaps (line 1993) | function allKeyMaps(cm) {
  function handleKeyBinding (line 2001) | function handleKeyBinding(cm, e) {
  function handleCharBinding (line 2038) | function handleCharBinding(cm, e, ch) {
  function onKeyDown (line 2050) | function onKeyDown(e) {
  function onKeyPress (line 2068) | function onKeyPress(e) {
  function onFocus (line 2084) | function onFocus(cm) {
  function onBlur (line 2096) | function onBlur(cm) {
  function onContextMenu (line 2107) | function onContextMenu(cm, e) {
  function clipPostChange (line 2175) | function clipPostChange(doc, change, pos) {
  function computeSelAfterChange (line 2191) | function computeSelAfterChange(doc, change, hint) {
  function filterChange (line 2214) | function filterChange(doc, change, update) {
  function makeChange (line 2238) | function makeChange(doc, change, selUpdate, ignoreReadOnly) {
  function makeChangeNoReadonly (line 2262) | function makeChangeNoReadonly(doc, change, selUpdate) {
  function makeChangeFromHistory (line 2278) | function makeChangeFromHistory(doc, type) {
  function shiftDoc (line 2318) | function shiftDoc(doc, distance) {
  function makeChangeSingleDoc (line 2326) | function makeChangeSingleDoc(doc, change, selAfter, spans) {
  function makeChangeSingleDocInEditor (line 2356) | function makeChangeSingleDocInEditor(cm, change, spans, selAfter) {
  function replaceRange (line 2408) | function replaceRange(doc, code, from, to, origin) {
  function Pos (line 2417) | function Pos(line, ch) {
  function posEq (line 2423) | function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}
  function posLess (line 2424) | function posLess(a, b) {return a.line < b.line || (a.line == b.line && a...
  function copyPos (line 2425) | function copyPos(x) {return Pos(x.line, x.ch);}
  function clipLine (line 2429) | function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.fi...
  function clipPos (line 2430) | function clipPos(doc, pos) {
  function clipToLen (line 2436) | function clipToLen(pos, linelen) {
  function isLine (line 2442) | function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.si...
  function extendSelection (line 2446) | function extendSelection(doc, pos, other, bias) {
  function filterSelectionChange (line 2465) | function filterSelectionChange(doc, anchor, head) {
  function setSelection (line 2476) | function setSelection(doc, anchor, head, bias, checkAtomic) {
  function reCheckSelection (line 2505) | function reCheckSelection(cm) {
  function skipAtomic (line 2509) | function skipAtomic(doc, pos, bias, mayClear) {
  function scrollCursorIntoView (line 2561) | function scrollCursorIntoView(cm) {
  function scrollPosIntoView (line 2579) | function scrollPosIntoView(cm, pos, margin) {
  function scrollIntoView (line 2597) | function scrollIntoView(cm, x1, y1, x2, y2) {
  function calculateScrollPos (line 2603) | function calculateScrollPos(cm, x1, y1, x2, y2) {
  function updateScrollPos (line 2629) | function updateScrollPos(cm, left, top) {
  function addToScrollPos (line 2634) | function addToScrollPos(cm, left, top) {
  function indentLine (line 2643) | function indentLine(cm, n, how, aggressive) {
  function changeLine (line 2683) | function changeLine(cm, handle, op) {
  function findPosH (line 2693) | function findPosH(doc, pos, dir, unit, visually) {
  function findPosV (line 2738) | function findPosV(cm, pos, dir, unit) {
  function findWordAt (line 2755) | function findWordAt(line, pos) {
  function selectLine (line 2769) | function selectLine(cm, line) {
  function interpret (line 3101) | function interpret(val) {
  function option (line 3143) | function option(name, deflt, handle, notOnInit) {
  function copyState (line 3303) | function copyState(mode, state) {
  function startState (line 3316) | function startState(mode, a1, a2) {
  function getKeyMap (line 3456) | function getKeyMap(val) {
  function lookupKey (line 3461) | function lookupKey(name, maps, handle) {
  function isModifierKey (line 3485) | function isModifierKey(event) {
  function keyName (line 3489) | function keyName(event, noShift) {
  function save (line 3522) | function save() {textarea.value = cm.getValue();}
  function StringStream (line 3564) | function StringStream(string, tabSize) {
  function TextMarker (line 3630) | function TextMarker(doc, type) {
  function markText (line 3717) | function markText(doc, from, to, options, type) {
  function SharedTextMarker (line 3779) | function SharedTextMarker(markers, primary) {
  function markTextShared (line 3800) | function markTextShared(doc, from, to, options, type) {
  function getMarkedSpanFor (line 3817) | function getMarkedSpanFor(spans, marker) {
  function removeMarkedSpan (line 3823) | function removeMarkedSpan(spans, span) {
  function addMarkedSpan (line 3828) | function addMarkedSpan(line, span) {
  function markedSpansBefore (line 3833) | function markedSpansBefore(old, startCh, isInsert) {
  function markedSpansAfter (line 3847) | function markedSpansAfter(old, endCh, isInsert) {
  function stretchSpansOverChange (line 3861) | function stretchSpansOverChange(doc, change) {
  function mergeOldSpans (line 3924) | function mergeOldSpans(doc, change) {
  function removeReadOnlyRanges (line 3946) | function removeReadOnlyRanges(doc, from, to) {
  function collapsedSpanAt (line 3974) | function collapsedSpanAt(line, ch) {
  function collapsedSpanAtStart (line 3986) | function collapsedSpanAtStart(line) { return collapsedSpanAt(line, -1); }
  function collapsedSpanAtEnd (line 3987) | function collapsedSpanAtEnd(line) { return collapsedSpanAt(line, line.te...
  function visualLine (line 3989) | function visualLine(doc, line) {
  function lineIsHidden (line 3996) | function lineIsHidden(doc, line) {
  function lineIsHiddenInner (line 4007) | function lineIsHiddenInner(doc, line, span) {
  function detachMarkedSpans (line 4022) | function detachMarkedSpans(line) {
  function attachMarkedSpans (line 4030) | function attachMarkedSpans(line, spans) {
  function widgetOperation (line 4045) | function widgetOperation(f) {
  function widgetHeight (line 4072) | function widgetHeight(widget) {
  function addLineWidget (line 4079) | function addLineWidget(cm, handle, node, options) {
  function makeLine (line 4099) | function makeLine(text, markedSpans, estimateHeight) {
  function updateLine (line 4106) | function updateLine(line, text, markedSpans, estimateHeight) {
  function cleanUpLine (line 4117) | function cleanUpLine(line) {
  function runMode (line 4125) | function runMode(cm, text, mode, state, f) {
  function highlightLine (line 4149) | function highlightLine(cm, line, state) {
  function getLineStyles (line 4185) | function getLineStyles(cm, line) {
  function processLine (line 4193) | function processLine(cm, line, state) {
  function styleToClass (line 4204) | function styleToClass(style) {
  function lineContent (line 4210) | function lineContent(cm, realLine, measure) {
  function buildToken (line 4259) | function buildToken(builder, text, style, startStyle, endStyle) {
  function buildTokenMeasure (line 4297) | function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
  function buildTokenSplitSpaces (line 4321) | function buildTokenSplitSpaces(inner) {
  function buildCollapsedSpan (line 4333) | function buildCollapsedSpan(builder, size, widget) {
  function insertLineContent (line 4348) | function insertLineContent(line, builder, styles) {
  function updateDoc (line 4408) | function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
  function LeafChunk (line 4454) | function LeafChunk(lines) {
  function BranchChunk (line 4489) | function BranchChunk(children) {
  function linkedDocs (line 4823) | function linkedDocs(doc, f, sharedHistOnly) {
  function attachDoc (line 4837) | function attachDoc(cm, doc) {
  function getLine (line 4850) | function getLine(chunk, n) {
  function getBetween (line 4862) | function getBetween(doc, start, end) {
  function getLines (line 4873) | function getLines(doc, from, to) {
  function updateLineHeight (line 4879) | function updateLineHeight(line, height) {
  function lineNo (line 4884) | function lineNo(line) {
  function lineAtHeight (line 4896) | function lineAtHeight(chunk, h) {
  function heightAtLine (line 4915) | function heightAtLine(cm, lineObj) {
  function getOrder (line 4934) | function getOrder(line) {
  function makeHistory (line 4942) | function makeHistory(startGen) {
  function attachLocalSpans (line 4956) | function attachLocalSpans(doc, change, from, to) {
  function historyChangeFromChange (line 4965) | function historyChangeFromChange(doc, change) {
  function addToHistory (line 4972) | function addToHistory(doc, change, selAfter, opId) {
  function removeClearedSpans (line 5009) | function removeClearedSpans(spans) {
  function getOldSpans (line 5018) | function getOldSpans(doc, change) {
  function copyHistoryArray (line 5028) | function copyHistoryArray(events, newGroup) {
  function rebaseHistSel (line 5049) | function rebaseHistSel(pos, from, to, diff) {
  function rebaseHistArray (line 5065) | function rebaseHistArray(array, from, to, diff) {
  function rebaseHist (line 5094) | function rebaseHist(hist, change) {
  function stopMethod (line 5102) | function stopMethod() {e_stop(this);}
  function addStop (line 5104) | function addStop(event) {
  function e_preventDefault (line 5109) | function e_preventDefault(e) {
  function e_stopPropagation (line 5113) | function e_stopPropagation(e) {
  function e_defaultPrevented (line 5117) | function e_defaultPrevented(e) {
  function e_stop (line 5120) | function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
  function e_target (line 5125) | function e_target(e) {return e.target || e.srcElement;}
  function e_button (line 5126) | function e_button(e) {
  function on (line 5139) | function on(emitter, type, f) {
  function off (line 5151) | function off(emitter, type, f) {
  function signal (line 5164) | function signal(emitter, type /*, values...*/) {
  function signalLater (line 5172) | function signalLater(emitter, type /*, values...*/) {
  function signalDOMEvent (line 5186) | function signalDOMEvent(cm, e) {
  function fireDelayed (line 5191) | function fireDelayed() {
  function hasHandler (line 5198) | function hasHandler(emitter, type) {
  function Delayed (line 5214) | function Delayed() {this.id = null;}
  function countColumn (line 5219) | function countColumn(string, end, tabSize, startIndex, startValue) {
  function spaceStr (line 5233) | function spaceStr(n) {
  function lst (line 5239) | function lst(arr) { return arr[arr.length-1]; }
  function selectInput (line 5241) | function selectInput(node) {
  function indexOf (line 5252) | function indexOf(collection, elt) {
  function createObj (line 5259) | function createObj(base, props) {
  function copyObj (line 5267) | function copyObj(obj, target) {
  function emptyArray (line 5273) | function emptyArray(size) {
  function bind (line 5278) | function bind(f) {
  function isWordChar (line 5284) | function isWordChar(ch) {
  function isEmpty (line 5289) | function isEmpty(obj) {
  function elt (line 5298) | function elt(tag, content, className, style) {
  function removeChildren (line 5307) | function removeChildren(e) {
  function removeChildrenAndAdd (line 5313) | function removeChildrenAndAdd(parent, e) {
  function setTextContent (line 5317) | function setTextContent(e, str) {
  function getRect (line 5324) | function getRect(node) {
  function spanAffectsWrapping (line 5347) | function spanAffectsWrapping() { return false; }
  function scrollbarWidth (line 5364) | function scrollbarWidth(measure) {
  function zeroWidthElement (line 5374) | function zeroWidthElement(measure) {
  function iterateBidiSections (line 5444) | function iterateBidiSections(order, from, to, f) {
  function bidiLeft (line 5453) | function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
  function bidiRight (line 5454) | function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
  function lineLeft (line 5456) | function lineLeft(line) { var order = getOrder(line); return order ? bid...
  function lineRight (line 5457) | function lineRight(line) {
  function lineStart (line 5463) | function lineStart(cm, lineN) {
  function lineEnd (line 5471) | function lineEnd(cm, lineN) {
  function compareBidiLevel (line 5480) | function compareBidiLevel(order, a, b) {
  function getBidiPartAt (line 5487) | function getBidiPartAt(order, pos) {
  function moveInLine (line 5507) | function moveInLine(line, pos, dir, byUnit) {
  function moveVisually (line 5520) | function moveVisually(line, start, dir, byUnit) {
  function moveLogically (line 5543) | function moveLogically(line, start, dir, byUnit) {
  function charType (line 5577) | function charType(code) {

FILE: editor/scripts/editor.js
  function updateExpand (line 71) | function updateExpand() {
  function run (line 92) | function run() {

FILE: editor/scripts/escodegen.js
  function require (line 3) | function require(file, parentModule) {
  function getDefaultOptions (line 167) | function getDefaultOptions() {
  function stringRepeat (line 203) | function stringRepeat(str, num) {
  function hasLineTerminator (line 218) | function hasLineTerminator(str) {
  function endsWithLineTerminator (line 221) | function endsWithLineTerminator(str) {
  function updateDeeply (line 225) | function updateDeeply(target, override) {
  function generateNumber (line 246) | function generateNumber(value) {
  function escapeRegExpCharacter (line 293) | function escapeRegExpCharacter(ch, previousIsBackslash) {
  function generateRegExp (line 301) | function generateRegExp(reg) {
  function escapeAllowedCharacter (line 338) | function escapeAllowedCharacter(code, next) {
  function escapeDisallowedCharacter (line 365) | function escapeDisallowedCharacter(code) {
  function escapeDirective (line 388) | function escapeDirective(str) {
  function escapeString (line 405) | function escapeString(str) {
  function flattenToString (line 440) | function flattenToString(arr) {
  function toSourceNodeWhenNeeded (line 448) | function toSourceNodeWhenNeeded(generated, node) {
  function noEmptySpace (line 468) | function noEmptySpace() {
  function join (line 471) | function join(left, right) {
  function addIndent (line 491) | function addIndent(stmt) {
  function withIndent (line 497) | function withIndent(fn) {
  function calculateSpaces (line 505) | function calculateSpaces(str) {
  function adjustMultilineComment (line 514) | function adjustMultilineComment(value, specialBase) {
  function generateComment (line 547) | function generateComment(comment, specialBase) {
  function addCommentsToStatement (line 560) | function addCommentsToStatement(stmt, result) {
  function parenthesize (line 621) | function parenthesize(text, current, should) {
  function maybeBlock (line 631) | function maybeBlock(stmt, semicolonOptional, functionBody) {
  function maybeBlockSuffix (line 654) | function maybeBlockSuffix(stmt, result) {
  function generateVerbatim (line 674) | function generateVerbatim(expr, option) {
  function generateIdentifier (line 683) | function generateIdentifier(node) {
  function generatePattern (line 686) | function generatePattern(node, options) {
  function generateFunctionBody (line 699) | function generateFunctionBody(node) {
  function generateExpression (line 740) | function generateExpression(expr, option) {
  function generateStatement (line 1305) | function generateStatement(stmt, option) {
  function generate (line 1760) | function generate(node, options) {
  function SourceNode (line 1963) | function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
  function addMappingWithCode (line 2023) | function addMappingWithCode(mapping, code) {
  function getArg (line 2191) | function getArg(aArgs, aName, aDefaultValue) {
  function urlParse (line 2203) | function urlParse(aUrl) {
  function urlGenerate (line 2217) | function urlGenerate(aParsedUrl) {
  function join (line 2234) | function join(aRoot, aPath) {
  function toSetString (line 2246) | function toSetString(aStr) {
  function fromSetString (line 2250) | function fromSetString(aStr) {
  function relative (line 2254) | function relative(aRoot, aPath) {
  function strcmp (line 2263) | function strcmp(aStr1, aStr2) {
  function compareByOriginalPositions (line 2268) | function compareByOriginalPositions(mappingA, mappingB, onlyCompareOrigi...
  function compareByGeneratedPositions (line 2294) | function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGene...
  function amdefine (line 2324) | function amdefine(module, requireFn) {
  function SourceMapGenerator (line 2523) | function SourceMapGenerator(aArgs) {
  function ArraySet (line 2753) | function ArraySet() {
  function toVLQSigned (line 2805) | function toVLQSigned(aValue) {
  function fromVLQSigned (line 2808) | function fromVLQSigned(aValue) {
  function SourceMapConsumer (line 2884) | function SourceMapConsumer(aSourceMap) {
  function recursiveSearch (line 3124) | function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) {
  function isStrictModeReservedWordES6 (line 3157) | function isStrictModeReservedWordES6(id) {
  function isKeywordES5 (line 3172) | function isKeywordES5(id, strict) {
  function isKeywordES6 (line 3178) | function isKeywordES6(id, strict) {
  function isRestrictedWord (line 3203) | function isRestrictedWord(id) {
  function isIdentifierName (line 3206) | function isIdentifierName(id) {
  function isDecimalDigit (line 3239) | function isDecimalDigit(ch) {
  function isHexDigit (line 3242) | function isHexDigit(ch) {
  function isOctalDigit (line 3245) | function isOctalDigit(ch) {
  function isWhiteSpace (line 3248) | function isWhiteSpace(ch) {
  function isLineTerminator (line 3269) | function isLineTerminator(ch) {
  function isIdentifierStart (line 3272) | function isIdentifierStart(ch) {
  function isIdentifierPart (line 3275) | function isIdentifierPart(ch) {
  function ignoreJSHintError (line 3353) | function ignoreJSHintError() {
  function deepCopy (line 3361) | function deepCopy(obj) {
  function shallowCopy (line 3375) | function shallowCopy(obj) {
  function upperBound (line 3385) | function upperBound(array, func) {
  function lowerBound (line 3401) | function lowerBound(array, func) {
  function Reference (line 3571) | function Reference(parent, key) {
  function Element (line 3578) | function Element(node, path, wrap, ref) {
  function Controller (line 3584) | function Controller() {
  function addToPath (line 3588) | function addToPath(result, path) {
  function traverse (line 3787) | function traverse(root, visitor) {
  function replace (line 3791) | function replace(root, visitor) {
  function extendCommentRange (line 3795) | function extendCommentRange(comment, tokens) {
  function attachComments (line 3813) | function attachComments(tree, providedComments, tokens) {

FILE: editor/scripts/escope.js
  function namespace (line 53) | function namespace(str, obj) {
  function assert (line 122) | function assert(cond, text) {
  function defaultOptions (line 128) | function defaultOptions() {
  function updateDeeply (line 135) | function updateDeeply(target, override) {
  function Reference (line 163) | function Reference(ident, scope, flag, writeExpr, maybeImplicitGlobal) {
  function Variable (line 282) | function Variable(name, scope) {
  function isStrictScope (line 336) | function isStrictScope(scope, block) {
  function Scope (line 389) | function Scope(block, opt) {
  function ScopeManager (line 768) | function ScopeManager(scopes) {
  function analyze (line 845) | function analyze(tree, providedOptions) {

FILE: editor/scripts/estraverse.js
  function ignoreJSHintError (line 102) | function ignoreJSHintError() { }
  function deepCopy (line 111) | function deepCopy(obj) {
  function shallowCopy (line 126) | function shallowCopy(obj) {
  function upperBound (line 140) | function upperBound(array, func) {
  function lowerBound (line 159) | function lowerBound(array, func) {
  function Reference (line 240) | function Reference(parent, key) {
  function Element (line 249) | function Element(node, path, wrap, ref) {
  function Controller (line 256) | function Controller() { }
  function addToPath (line 263) | function addToPath(result, path) {
  function traverse (line 553) | function traverse(root, visitor) {
  function replace (line 558) | function replace(root, visitor) {
  function extendCommentRange (line 563) | function extendCommentRange(comment, tokens) {
  function attachComments (line 584) | function attachComments(tree, providedComments, tokens) {

FILE: editor/scripts/expander.js
  function StringMap (line 52) | function StringMap(o) {
  function remdup (line 83) | function remdup(mark, mlist) {
  function marksof (line 90) | function marksof(ctx, stopName, originalName) {
  function resolve (line 109) | function resolve(stx) {
  function resolveCtx (line 138) | function resolveCtx(originalName, ctx, stop_spine, stop_branch, cache) {
  function resolveCtxFull (line 146) | function resolveCtxFull(originalName, ctx, stop_spine, stop_branch, cach...
  function arraysEqual (line 183) | function arraysEqual(a, b) {
  function renames (line 194) | function renames(defctx, oldctx, originalName) {
  function unionEl (line 203) | function unionEl(arr, el) {
  function fresh (line 213) | function fresh() {
  function wrapDelim (line 218) | function wrapDelim(towrap, delimSyntax) {
  function getParamIdentifiers (line 230) | function getParamIdentifiers(argSyntax) {
  function inherit (line 241) | function inherit(parent, child, methods) {
  function TermTree (line 251) | function TermTree() {
  function EOF (line 330) | function EOF(eof) {
  function Keyword (line 338) | function Keyword(keyword) {
  function Punc (line 346) | function Punc(punc) {
  function Delimiter (line 354) | function Delimiter(delim) {
  function LetMacro (line 362) | function LetMacro(name, body) {
  function Macro (line 374) | function Macro(name, body) {
  function AnonMacro (line 386) | function AnonMacro(body) {
  function OperatorDefinition (line 394) | function OperatorDefinition(type, name, prec, assoc, body) {
  function Module (line 412) | function Module(body, exports$3) {
  function Export (line 424) | function Export(name) {
  function VariableDeclaration (line 432) | function VariableDeclaration(ident, eq, init, comma) {
  function Statement (line 448) | function Statement() {
  function Empty (line 455) | function Empty() {
  function CatchClause (line 462) | function CatchClause(keyword, params, body) {
  function ForStatement (line 476) | function ForStatement(keyword, cond) {
  function ReturnStatement (line 488) | function ReturnStatement(keyword, expr) {
  function Expr (line 511) | function Expr() {
  function UnaryOp (line 518) | function UnaryOp(op, expr) {
  function PostfixOp (line 530) | function PostfixOp(expr, op) {
  function BinOp (line 542) | function BinOp(left, op, right) {
  function AssignmentExpression (line 556) | function AssignmentExpression(left, op, right) {
  function ConditionalExpression (line 570) | function ConditionalExpression(cond, question, tru, colon, fls) {
  function NamedFun (line 588) | function NamedFun(keyword, star, name, params, body) {
  function AnonFun (line 606) | function AnonFun(keyword, star, params, body) {
  function ArrowFun (line 622) | function ArrowFun(params, arrow, body) {
  function ObjDotGet (line 636) | function ObjDotGet(left, dot, right) {
  function ObjGet (line 650) | function ObjGet(left, right) {
  function Template (line 662) | function Template(template) {
  function Call (line 670) | function Call(fun, args) {
  function PrimaryExpression (line 682) | function PrimaryExpression() {
  function ThisExpression (line 689) | function ThisExpression(keyword) {
  function Lit (line 697) | function Lit(lit) {
  function Block (line 705) | function Block(body) {
  function ArrayLiteral (line 713) | function ArrayLiteral(array) {
  function Id (line 721) | function Id(id) {
  function Partial (line 729) | function Partial() {
  function PartialOperation (line 736) | function PartialOperation(stx, left) {
  function PartialExpression (line 748) | function PartialExpression(stx, left, combine) {
  function BindingStatement (line 762) | function BindingStatement(keyword, decls) {
  function VariableStatement (line 782) | function VariableStatement(keyword, decls) {
  function LetStatement (line 794) | function LetStatement(keyword, decls) {
  function ConstStatement (line 806) | function ConstStatement(keyword, decls) {
  function ParenExpression (line 818) | function ParenExpression(args, delim, commas) {
  function stxIsUnaryOp (line 855) | function stxIsUnaryOp(stx) {
  function stxIsBinOp (line 871) | function stxIsBinOp(stx) {
  function getUnaryOpPrec (line 899) | function getUnaryOpPrec(op) {
  function getBinaryOpPrec (line 915) | function getBinaryOpPrec(op) {
  function getBinaryOpAssoc (line 943) | function getBinaryOpAssoc(op) {
  function stxIsAssignOp (line 971) | function stxIsAssignOp(stx) {
  function enforestVarStatement (line 988) | function enforestVarStatement(stx, context, varStx) {
  function enforestAssignment (line 1031) | function enforestAssignment(stx, context, left, prevStx, prevTerms) {
  function enforestParenExpression (line 1062) | function enforestParenExpression(parens, context) {
  function adjustLineContext (line 1086) | function adjustLineContext(stx, original, current) {
  function getName (line 1148) | function getName(head, rest) {
  function getMacroInEnv (line 1163) | function getMacroInEnv(head, rest, env) {
  function nameInEnv (line 1192) | function nameInEnv(head, rest, env) {
  function resolveFast (line 1197) | function resolveFast(stx, env) {
  function expandMacro (line 1201) | function expandMacro(stx, context, opCtx, opType, macroObj) {
  function comparePrec (line 1264) | function comparePrec(left, right, assoc) {
  function enforest (line 1272) | function enforest(toks, context, prevStx, prevTerms) {
  function rewindOpCtx (line 1763) | function rewindOpCtx(opCtx, res) {
  function get_expression (line 1814) | function get_expression(stx, context) {
  function tagWithTerm (line 1861) | function tagWithTerm(term, stx) {
  function applyMarkToPatternEnv (line 1877) | function applyMarkToPatternEnv(newMark, env) {
  function loadMacroDef (line 1907) | function loadMacroDef(body, context) {
  function expandToTermTree (line 2000) | function expandToTermTree(stx, context) {
  function addToDefinitionCtx (line 2142) | function addToDefinitionCtx(idents, defscope, skipRep, paramscope) {
  function expandTermTreeToFinal (line 2189) | function expandTermTreeToFinal(term, context) {
  function expand (line 2350) | function expand(stx, context) {
  function makeExpanderContext (line 2361) | function makeExpanderContext(o) {
  function makeTopLevelExpanderContext (line 2419) | function makeTopLevelExpanderContext(options) {
  function expandTopLevel (line 2428) | function expandTopLevel(stx, moduleContexts, options) {
  function expandModule (line 2449) | function expandModule(stx, moduleContexts, options) {
  function loadModuleExports (line 2482) | function loadModuleExports(stx, newEnv, exports$3, oldEnv) {
  function flatten (line 2495) | function flatten(stx) {

FILE: editor/scripts/jquery.js
  function isArraylike (line 848) | function isArraylike( obj ) {
  function Sizzle (line 1048) | function Sizzle( selector, context, results, seed ) {
  function createCache (line 1163) | function createCache() {
  function markFunction (line 1181) | function markFunction( fn ) {
  function assert (line 1190) | function assert( fn ) {
  function addHandle (line 1212) | function addHandle( attrs, handler ) {
  function siblingCheck (line 1227) | function siblingCheck( a, b ) {
  function createInputPseudo (line 1254) | function createInputPseudo( type ) {
  function createButtonPseudo (line 1265) | function createButtonPseudo( type ) {
  function createPositionalPseudo (line 1276) | function createPositionalPseudo( fn ) {
  function setFilters (line 2259) | function setFilters() {}
  function tokenize (line 2263) | function tokenize( selector, parseOnly ) {
  function toSelector (line 2330) | function toSelector( tokens ) {
  function addCombinator (line 2340) | function addCombinator( matcher, combinator, base ) {
  function elementMatcher (line 2390) | function elementMatcher( matchers ) {
  function condense (line 2404) | function condense( unmatched, map, filter, context, xml ) {
  function setMatcher (line 2425) | function setMatcher( preFilter, selector, matcher, postFilter, postFinde...
  function matcherFromTokens (line 2518) | function matcherFromTokens( tokens ) {
  function matcherFromGroupMatchers (line 2573) | function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  function multipleContexts (line 2701) | function multipleContexts( selector, contexts, results ) {
  function select (line 2710) | function select( selector, context, results, seed ) {
  function createOptions (line 2850) | function createOptions( options ) {
  function Data (line 3312) | function Data() {
  function dataAttr (line 3625) | function dataAttr( elem, key, data ) {
  function returnTrue (line 4305) | function returnTrue() {
  function returnFalse (line 4309) | function returnFalse() {
  function safeActiveElement (line 4313) | function safeActiveElement() {
  function sibling (line 5268) | function sibling( cur, dir ) {
  function winnow (line 5384) | function winnow( elements, qualifier, not ) {
  function manipulationTarget (line 5893) | function manipulationTarget( elem, content ) {
  function disableScript (line 5903) | function disableScript( elem ) {
  function restoreScript (line 5907) | function restoreScript( elem ) {
  function setGlobalEval (line 5920) | function setGlobalEval( elems, refElements ) {
  function cloneCopyEvent (line 5931) | function cloneCopyEvent( src, dest ) {
  function getAll (line 5966) | function getAll( context, tag ) {
  function fixInput (line 5977) | function fixInput( src, dest ) {
  function vendorPropName (line 6078) | function vendorPropName( style, name ) {
  function isHidden (line 6100) | function isHidden( elem, el ) {
  function getStyles (line 6109) | function getStyles( elem ) {
  function showHide (line 6113) | function showHide( elements, show ) {
  function setPositiveNumber (line 6384) | function setPositiveNumber( elem, value, subtract ) {
  function augmentWidthOrHeight (line 6392) | function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
  function getWidthOrHeight (line 6431) | function getWidthOrHeight( elem, name, extra ) {
  function css_defaultDisplay (line 6475) | function css_defaultDisplay( nodeName ) {
  function actualDisplay (line 6507) | function actualDisplay( name, doc ) {
  function buildParams (line 6693) | function buildParams( prefix, obj, traditional, add ) {
  function addToPrefiltersOrTransports (line 6809) | function addToPrefiltersOrTransports( structure ) {
  function inspectPrefiltersOrTransports (line 6841) | function inspectPrefiltersOrTransports( structure, options, originalOpti...
  function ajaxExtend (line 6868) | function ajaxExtend( target, src ) {
  function done (line 7314) | function done( status, nativeStatusText, responses, headers ) {
  function ajaxHandleResponses (line 7461) | function ajaxHandleResponses( s, jqXHR, responses ) {
  function ajaxConvert (line 7517) | function ajaxConvert( s, response, jqXHR, isSuccess ) {
  function createFxNow (line 7912) | function createFxNow() {
  function createTween (line 7919) | function createTween( value, prop, animation ) {
  function Animation (line 7933) | function Animation( elem, properties, options ) {
  function propFilter (line 8037) | function propFilter( props, specialEasing ) {
  function defaultPrefilter (line 8104) | function defaultPrefilter( elem, props, opts ) {
  function Tween (line 8227) | function Tween( elem, options, prop, end, easing ) {
  function genFx (line 8451) | function genFx( type, includeWidth ) {
  function getWindow (line 8749) | function getWindow( elem ) {

FILE: editor/scripts/mori.js
  function n (line 15) | function n(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)...
  function r (line 16) | function r(a,b){var c=a.split("."),d=aa;c[0]in d||!d.execScript||d.execS...
  function da (line 16) | function da(a){return Array.prototype.join.call(arguments,"")}
  function ea (line 16) | function ea(a,b){for(var c in a)b.call(void 0,a[c],c,a)}
  function fa (line 16) | function fa(a,b){null!=a&&this.append.apply(this,arguments)}
  function ga (line 16) | function ga(a,b){a.sort(b||ha)}
  function ia (line 16) | function ia(a,b){for(var c=0;c<a.length;c++)a[c]={index:c,value:a[c]};va...
  function ha (line 16) | function ha(a,b){return a>b?1:a<b?-1:0}
  function oa (line 16) | function oa(){return new pa(null,5,[sa,!0,ua,!0,wa,!1,ya,!1,za,la],null)}
  function t (line 16) | function t(a){return null!=a&&!1!==a}
  function Aa (line 16) | function Aa(a){return t(a)?!1:!0}
  function w (line 16) | function w(a,b){return a[n(null==b?null:b)]?!0:a._?!0:!1}
  function Ba (line 16) | function Ba(a){return null==a?null:a.constructor}
  function x (line 17) | function x(a,b){var c=Ba(b),c=t(t(c)?c.Yb:c)?c.Xb:n(b);return Error(["No...
  function Da (line 17) | function Da(a){var b=a.Xb;return t(b)?b:""+z(a)}
  function Fa (line 17) | function Fa(a){for(var b=a.length,c=Array(b),d=0;;)if(d<b)c[d]=a[d],d+=1...
  function Ha (line 17) | function Ha(a){for(var b=Array(arguments.length),c=0;;)if(c<b.length)b[c...
  function a (line 18) | function a(a,b){function c(a,b){a.push(b);return a}var g=[];return A.c?A...
  function b (line 18) | function b(a){return c.a(null,a)}
  function Ma (line 18) | function Ma(a){if(a?a.L:a)return a.L(a);var b;b=Ma[n(null==a?null:a)];if...
  function Na (line 19) | function Na(a){if(a?a.J:a)return a.J(a);var b;b=Na[n(null==a?null:a)];if...
  function Ra (line 19) | function Ra(a,b){if(a?a.G:a)return a.G(a,b);var c;c=Ra[n(null==a?null:a)...
  function a (line 20) | function a(a,b,c){if(a?a.$:a)return a.$(a,b,c);var g;g=C[n(null==a?null:...
  function b (line 20) | function b(a,b){if(a?a.Q:a)return a.Q(a,b);var c;c=C[n(null==a?null:a)];...
  function Va (line 21) | function Va(a){if(a?a.N:a)return a.N(a);var b;b=Va[n(null==a?null:a)];if...
  function Wa (line 21) | function Wa(a){if(a?a.S:a)return a.S(a);var b;b=Wa[n(null==a?null:a)];if...
  function a (line 22) | function a(a,b,c){if(a?a.s:a)return a.s(a,b,c);var g;g=$a[n(null==a?null...
  function b (line 22) | function b(a,b){if(a?a.t:a)return a.t(a,b);var c;c=$a[n(null==a?null:a)]...
  function bb (line 23) | function bb(a,b){if(a?a.rb:a)return a.rb(a,b);var c;c=bb[n(null==a?null:...
  function cb (line 23) | function cb(a,b,c){if(a?a.Ka:a)return a.Ka(a,b,c);var d;d=cb[n(null==a?n...
  function eb (line 23) | function eb(a,b){if(a?a.wb:a)return a.wb(a,b);var c;c=eb[n(null==a?null:...
  function hb (line 24) | function hb(a){if(a?a.hb:a)return a.hb(a);var b;b=hb[n(null==a?null:a)];...
  function ib (line 24) | function ib(a){if(a?a.ib:a)return a.ib(a);var b;b=ib[n(null==a?null:a)];...
  function kb (line 24) | function kb(a,b){if(a?a.Eb:a)return a.Eb(a,b);var c;c=kb[n(null==a?null:...
  function lb (line 25) | function lb(a){if(a?a.La:a)return a.La(a);var b;b=lb[n(null==a?null:a)];...
  function mb (line 25) | function mb(a){if(a?a.Ma:a)return a.Ma(a);var b;b=mb[n(null==a?null:a)];...
  function pb (line 25) | function pb(a,b,c){if(a?a.Ua:a)return a.Ua(a,b,c);var d;d=pb[n(null==a?n...
  function qb (line 26) | function qb(a){if(a?a.Ra:a)return a.Ra(a);var b;b=qb[n(null==a?null:a)];...
  function sb (line 26) | function sb(a){if(a?a.H:a)return a.H(a);var b;b=sb[n(null==a?null:a)];if...
  function ub (line 26) | function ub(a,b){if(a?a.F:a)return a.F(a,b);var c;c=ub[n(null==a?null:a)...
  function a (line 27) | function a(a,b,c){if(a?a.O:a)return a.O(a,b,c);var g;g=wb[n(null==a?null...
  function b (line 27) | function b(a,b){if(a?a.R:a)return a.R(a,b);var c;c=wb[n(null==a?null:a)]...
  function xb (line 28) | function xb(a,b,c){if(a?a.gb:a)return a.gb(a,b,c);var d;d=xb[n(null==a?n...
  function yb (line 28) | function yb(a,b){if(a?a.A:a)return a.A(a,b);var c;c=yb[n(null==a?null:a)...
  function zb (line 28) | function zb(a){if(a?a.B:a)return a.B(a);var b;b=zb[n(null==a?null:a)];if...
  function Cb (line 29) | function Cb(a){if(a?a.D:a)return a.D(a);var b;b=Cb[n(null==a?null:a)];if...
  function Gb (line 29) | function Gb(a){if(a?a.ab:a)return a.ab(a);var b;b=Gb[n(null==a?null:a)];...
  function Hb (line 29) | function Hb(a,b){if(a?a.Hb:a)return a.Hb(a,b);var c;c=Hb[n(null==a?null:...
  function Ib (line 30) | function Ib(a,b,c){if(a?a.Ib:a)return a.Ib(a,b,c);var d;d=Ib[n(null==a?n...
  function Jb (line 30) | function Jb(a,b){if(a?a.Gb:a)return a.Gb(a,b);var c;c=Jb[n(null==a?null:...
  function Kb (line 30) | function Kb(a){if(a?a.Fb:a)return a.Fb(a);var b;b=Kb[n(null==a?null:a)];...
  function Lb (line 31) | function Lb(a,b){if(a?a.Wb:a)return a.Wb(0,b);var c;c=Lb[n(null==a?null:...
  function Nb (line 31) | function Nb(a,b,c){if(a?a.v:a)return a.v(a,b,c);var d;d=Nb[n(null==a?nul...
  function Ob (line 31) | function Ob(a){if(a?a.$a:a)return a.$a(a);var b;b=Ob[n(null==a?null:a)];...
  function Pb (line 32) | function Pb(a,b){if(a?a.Sa:a)return a.Sa(a,b);var c;c=Pb[n(null==a?null:...
  function Qb (line 32) | function Qb(a){if(a?a.Ta:a)return a.Ta(a);var b;b=Qb[n(null==a?null:a)];...
  function Rb (line 32) | function Rb(a,b,c){if(a?a.kb:a)return a.kb(a,b,c);var d;d=Rb[n(null==a?n...
  function Sb (line 33) | function Sb(a,b){if(a?a.Jb:a)return a.Jb(a,b);var c;c=Sb[n(null==a?null:...
  function Tb (line 33) | function Tb(a,b,c){if(a?a.Ub:a)return a.Ub(0,b,c);var d;d=Tb[n(null==a?n...
  function Ub (line 33) | function Ub(a){if(a?a.Vb:a)return a.Vb();var b;b=Ub[n(null==a?null:a)];i...
  function Vb (line 34) | function Vb(a,b){if(a?a.Tb:a)return a.Tb(0,b);var c;c=Vb[n(null==a?null:...
  function Xb (line 34) | function Xb(a){if(a?a.Pb:a)return a.Pb();var b;b=Xb[n(null==a?null:a)];i...
  function Yb (line 34) | function Yb(a){if(a?a.Cb:a)return a.Cb(a);var b;b=Yb[n(null==a?null:a)];...
  function Zb (line 35) | function Zb(a){if(a?a.Db:a)return a.Db(a);var b;b=Zb[n(null==a?null:a)];...
  function $b (line 35) | function $b(a){if(a?a.Bb:a)return a.Bb(a);var b;b=$b[n(null==a?null:a)];...
  function ac (line 35) | function ac(a,b){if(a?a.bb:a)return a.bb(0,b);var c;c=ac[n(null==a?null:...
  function cc (line 36) | function cc(a){if(a?a.fb:a)return a.fb(a);var b;b=cc[n(null==a?null:a)];...
  function dc (line 36) | function dc(a){this.qc=a;this.q=0;this.j=1073741824}
  function ec (line 36) | function ec(a){var b=new fa;a.v(null,new dc(b),oa());return""+z(b)}
  function gc (line 37) | function gc(a){a=fc(a,3432918353);return fc(a<<15|a>>>-15,461845907)}
  function hc (line 37) | function hc(a,b){var c=a^b;return fc(c<<13|c>>>-13,5)+3864292196}
  function ic (line 38) | function ic(a,b){var c=a^b,c=fc(c^c>>>16,2246822507),c=fc(c^c>>>13,32664...
  function mc (line 38) | function mc(a){255<lc&&(kc={},lc=0);var b=kc[a];if("number"!==typeof b){...
  function nc (line 39) | function nc(a){a&&(a.j&4194304||a.vc)?a=a.B(null):"number"===typeof a?a=...
  function oc (line 40) | function oc(a){var b;b=a.name;var c;a:{c=1;for(var d=0;;)if(c<b.length){...
  function pc (line 40) | function pc(a,b){if(a.ta===b.ta)return 0;var c=Aa(a.ba);if(t(c?b.ba:c))r...
  function qc (line 41) | function qc(a,b,c,d,e){this.ba=a;this.name=b;this.ta=c;this.Ya=d;this.Z=...
  function a (line 43) | function a(a,b){var c=null!=a?[z(a),z("/"),z(b)].join(""):b;return new q...
  function b (line 43) | function b(a){return a instanceof qc?a:c.a(null,a)}
  function D (line 44) | function D(a){if(null==a)return null;if(a&&(a.j&8388608||a.mc))return a....
  function G (line 44) | function G(a){if(null==a)return null;if(a&&(a.j&64||a.jb))return a.N(nul...
  function H (line 44) | function H(a){return null!=a?a&&(a.j&64||a.jb)?a.S(null):(a=D(a))?Wa(a):...
  function K (line 44) | function K(a){return null==a?null:a&&(a.j&128||a.xb)?a.T(null):D(H(a))}
  function a (line 45) | function a(a,b){return null==a?null==b:a===b||yb(a,b)}
  function a (line 45) | function a(b,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function c (line 45) | function c(a,d,e){for(;;)if(b.a(a,d))if(K(e))a=d,d=G(e),e=K(e);else retu...
  function tc (line 46) | function tc(a){this.C=a}
  function uc (line 46) | function uc(a){return new tc(D(a))}
  function vc (line 47) | function vc(a,b){var c=gc(a),c=hc(0,c);return ic(c,b)}
  function wc (line 47) | function wc(a){var b=0,c=1;for(a=D(a);;)if(null!=a)b+=1,c=fc(31,c)+nc(G(...
  function xc (line 47) | function xc(a){var b=0,c=0;for(a=D(a);;)if(null!=a)b+=1,c=c+nc(G(a))|0,a...
  function yc (line 48) | function yc(a){this.o=a;this.q=0;this.j=32768}
  function Ac (line 48) | function Ac(a){return a instanceof yc}
  function Bc (line 48) | function Bc(a){return Ac(a)?L.b?L.b(a):L.call(null,a):a}
  function L (line 48) | function L(a){return qb(a)}
  function a (line 49) | function a(a,b,c,d){for(var l=Ma(a);;)if(d<l){var m=C.a(a,d);c=b.a?b.a(c...
  function b (line 49) | function b(a,b,c){var d=Ma(a),l=c;for(c=0;;)if(c<d){var m=C.a(a,c),l=b.a...
  function c (line 49) | function c(a,b){var c=Ma(a);if(0===c)return b.l?b.l():b.call(null);for(v...
  function a (line 50) | function a(a,b,c,d){for(var l=a.length;;)if(d<l){var m=a[d];c=b.a?b.a(c,...
  function b (line 50) | function b(a,b,c){var d=a.length,l=c;for(c=0;;)if(c<d){var m=a[c],l=b.a?...
  function c (line 50) | function c(a,
  function Ec (line 51) | function Ec(a){return a?a.j&2||a.cc?!0:a.j?!1:w(La,a):w(La,a)}
  function Fc (line 52) | function Fc(a){return a?a.j&16||a.Qb?!0:a.j?!1:w(Ta,a):w(Ta,a)}
  function Gc (line 52) | function Gc(a,b){this.e=a;this.m=b}
  function F (line 52) | function F(a,b){this.e=a;this.m=b;this.j=166199550;this.q=8192}
  function a (line 55) | function a(a,b){return b<a.length?new F(a,b):null}
  function b (line 55) | function b(a){return c.a(a,0)}
  function a (line 55) | function a(a,b){return Jc.a(a,b)}
  function b (line 55) | function b(a){return Jc.a(a,0)}
  function Hc (line 56) | function Hc(a,b,c){this.qb=a;this.m=b;this.k=c;this.j=32374990;this.q=8192}
  function Lc (line 57) | function Lc(a){return G(K(a))}
  function a (line 58) | function a(a,b){return null!=a?Ra(a,b):Ra(J,b)}
  function a (line 58) | function a(b,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function c (line 58) | function c(a,d,e){for(;;)if(t(e))a=b.a(a,d),d=G(e),e=K(e);else return b....
  function Oc (line 59) | function Oc(a){return null==a?null:Na(a)}
  function Q (line 60) | function Q(a){if(null!=a)if(a&&(a.j&2||a.cc))a=a.L(null);else if(a insta...
  function a (line 61) | function a(a,b,c){for(;;){if(null==a)return c;if(0===b)return D(a)?G(a):...
  function b (line 61) | function b(a,b){for(;;){if(null==a)throw Error("Index out of bounds");if...
  function a (line 62) | function a(a,b,c){if("number"!==typeof b)throw Error("index argument to ...
  function b (line 62) | function b(a,b){if("number"!==
  function a (line 64) | function a(a,b,c){return null!=a?a&&(a.j&256||a.Rb)?a.s(null,b,c):a inst...
  function b (line 64) | function b(a,b){return null==a?null:a&&(a.j&256||a.Rb)?a.t(null,b):a ins...
  function a (line 65) | function a(a,b,c){if(null!=a)a=cb(a,b,c);else a:{a=[b];c=[c];b=a.length;...
  function a (line 65) | function a(b,d,h,l){var m=null;if(3<arguments.length){for(var m=0,p=Arra...
  function c (line 65) | function c(a,d,e,l){for(;;)if(a=b.c(a,
  function a (line 66) | function a(a,
  function a (line 67) | function a(b,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function c (line 67) | function c(a,d,e){for(;;){if(null==a)return null;a=b.a(a,d);if(t(e))d=G(...
  function Tc (line 68) | function Tc(a){var b="function"==n(a);return t(b)?b:a?t(t(null)?null:a.b...
  function Uc (line 68) | function Uc(a,b){this.h=a;this.k=b;this.q=0;this.j=393217}
  function a (line 69) | function a(a,b,c,d,e,f,g,h,l,m,p,q,u,s,v,y,B,E,N,Y,ra,I){a=this.h;return...
  function b (line 69) | function b(a,b,c,d,e,f,g,h,l,m,p,q,u,s,v,y,B,E,N,Y,ra){a=this;return a.h...
  function c (line 69) | function c(a,b,c,d,e,f,g,h,l,m,p,q,u,s,v,y,B,E,N,Y){a=this;return a.h.Ea...
  function d (line 70) | function d(a,b,c,d,e,f,g,h,l,m,p,q,u,s,v,y,B,E,N){a=this;return a.h.Da?a...
  function e (line 70) | function e(a,b,c,d,e,f,g,h,l,m,p,q,u,s,v,y,B,E){a=this;return a.h.Ca?a.h...
  function f (line 70) | function f(a,b,c,d,e,f,g,h,l,m,p,q,u,s,v,y,B){a=this;return a.h.Ba?a.h.B...
  function g (line 71) | function g(a,b,c,d,e,f,g,h,l,m,p,q,u,s,v,y){a=this;return a.h.Aa?a.h.Aa(...
  function h (line 71) | function h(a,b,c,d,e,f,g,h,l,m,p,q,u,s,v){a=this;return a.h.za?a.h.za(b,...
  function l (line 71) | function l(a,b,c,d,e,f,g,h,l,m,p,q,u,s){a=this;return a.h.ya?a.h.ya(b,c,...
  function m (line 71) | function m(a,b,c,d,e,f,g,h,l,m,p,q,u){a=this;
  function p (line 72) | function p(a,b,c,d,e,f,g,h,l,m,p,q){a=this;return a.h.wa?a.h.wa(b,c,d,e,...
  function q (line 72) | function q(a,b,c,d,e,f,g,h,l,m,p){a=this;return a.h.va?a.h.va(b,c,d,e,f,...
  function s (line 72) | function s(a,b,c,d,e,f,g,h,l,m){a=this;return a.h.Ha?a.h.Ha(b,c,d,e,f,g,...
  function u (line 72) | function u(a,b,c,d,e,f,g,h,l){a=this;return a.h.Ga?a.h.Ga(b,c,
  function v (line 73) | function v(a,b,c,d,e,f,g,h){a=this;return a.h.ia?a.h.ia(b,c,d,e,f,g,h):a...
  function y (line 73) | function y(a,b,c,d,e,f,g){a=this;return a.h.P?a.h.P(b,c,d,e,f,g):a.h.cal...
  function B (line 73) | function B(a,b,c,d,e,f){a=this;return a.h.r?a.h.r(b,c,d,e,f):a.h.call(nu...
  function E (line 73) | function E(a,b,c,d,e){a=this;return a.h.n?a.h.n(b,c,d,e):a.h.call(null,b...
  function N (line 73) | function N(a,b,c,d){a=this;return a.h.c?a.h.c(b,c,d):a.h.call(null,b,c,d)}
  function Y (line 73) | function Y(a,b,c){a=this;
  function ra (line 74) | function ra(a,b){a=this;return a.h.b?a.h.b(b):a.h.call(null,b)}
  function Pa (line 74) | function Pa(a){a=this;return a.h.l?a.h.l():a.h.call(null)}
  function O (line 84) | function O(a,b){return Tc(a)&&!(a?a.j&262144||a.Bc||(a.j?0:w(tb,a)):w(tb...
  function Vc (line 84) | function Vc(a){var b=null!=a;return(b?a?a.j&131072||a.kc||(a.j?0:w(rb,a)...
  function Wc (line 85) | function Wc(a){return null==a?null:lb(a)}
  function a (line 86) | function a(a,b){return null==a?null:kb(a,b)}
  function a (line 86) | function a(b,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function c (line 86) | function c(a,d,e){for(;;){if(null==a)return null;a=b.a(a,d);if(t(e))d=G(...
  function Yc (line 87) | function Yc(a){return null==a||Aa(D(a))}
  function $c (line 87) | function $c(a){return null==a?!1:a?a.j&8||a.tc?!0:a.j?!1:w(Qa,a):w(Qa,a)}
  function ad (line 87) | function ad(a){return null==a?!1:a?a.j&4096||a.zc?!0:a.j?!1:w(jb,a):w(jb...
  function bd (line 88) | function bd(a){return a?a.j&512||a.rc?!0:a.j?!1:w(ab,a):w(ab,a)}
  function cd (line 88) | function cd(a){return a?a.j&16777216||a.yc?!0:a.j?!1:w(Db,a):w(Db,a)}
  function dd (line 88) | function dd(a){return null==a?!1:a?a.j&1024||a.ic?!0:a.j?!1:w(db,a):w(db...
  function ed (line 88) | function ed(a){return a?a.j&16384||a.Ac?!0:a.j?!1:w(nb,a):w(nb,a)}
  function fd (line 88) | function fd(a){return a?a.q&512||a.sc?!0:!1:!1}
  function gd (line 88) | function gd(a){var b=[];ea(a,function(a,b){return function(a,c){return b...
  function hd (line 88) | function hd(a,b,c,d,e){for(;0!==e;)c[d]=a[b],d+=1,e-=1,b+=1}
  function id (line 89) | function id(a,b,c,d,e){b+=e-1;for(d+=e-1;0!==e;)c[d]=a[b],d-=1,e-=1,b-=1}
  function kd (line 89) | function kd(a){return null==a?!1:a?a.j&64||a.jb?!0:a.j?!1:w(Ua,a):w(Ua,a)}
  function ld (line 89) | function ld(a){return a?a.j&8388608||a.mc?!0:a.j?!1:w(Bb,a):w(Bb,a)}
  function md (line 89) | function md(a){return t(a)?!0:!1}
  function nd (line 89) | function nd(a,b){return S.c(a,b,jd)===jd?!1:!0}
  function od (line 90) | function od(a,b){if(a===b)return 0;if(null==a)return-1;if(null==b)return...
  function a (line 91) | function a(a,b,c,g){for(;;){var h=od(R.a(a,g),R.a(b,g));if(0===h&&g+1<c)...
  function b (line 91) | function b(a,b){var f=Q(a),g=Q(b);return f<g?-1:f>g?1:c.n(a,b,f,0)}
  function qd (line 92) | function qd(a){return sc.a(a,od)?od:function(b,c){var d=a.a?a.a(b,c):a.c...
  function a (line 93) | function a(a,b){if(D(b)){var c=rd.b?rd.b(b):rd.call(null,b),g=qd(a);ia(c...
  function b (line 93) | function b(a){return c.a(od,a)}
  function a (line 93) | function a(a,b,c){return sd.a(function(c,f){return qd(b).call(null,a.b?a...
  function b (line 93) | function b(a,b){return c.c(a,od,
  function a (line 94) | function a(a,b,c){for(c=D(c);;)if(c){var g=G(c);b=a.a?a.a(b,g):a.call(nu...
  function b (line 94) | function b(a,b){var c=D(b);if(c){var g=G(c),c=K(c);return A.c?A.c(a,g,c)...
  function a (line 95) | function a(a,b,c){return c&&(c.j&524288||c.Sb)?c.O(null,a,b):c instanceo...
  function b (line 95) | function b(a,b){return b&&(b.j&524288||b.Sb)?b.R(null,a):b instanceof Ar...
  function ud (line 96) | function ud(a){return a}
  function a (line 97) | function a(a,b){return function(){function c(b,e){return a.a?a.a(b,e):a....
  function b (line 97) | function b(a){return c.a(a,ud)}
  function a (line 98) | function a(a,b,c,g){a=a.b?a.b(b):a.call(null,b);c=A.c(a,c,g);return a.b?...
  function b (line 98) | function b(a,b,f){return c.n(a,b,b.l?b.l():b.call(null),f)}
  function b (line 98) | function b(a,
  function d (line 99) | function d(b,c,d){return A.c(a,b+c,d)}
  function a (line 100) | function a(c,f,g){var h=null;if(2<arguments.length){for(var h=0,l=Array(...
  function b (line 100) | function b(a,c,d){for(;;)if(a<c)if(K(d))a=c,c=G(d),d=K(d);else return c<...
  function a (line 101) | function a(c,f,g){var h=null;if(2<
  function b (line 102) | function b(a,c,d){for(;;)if(a<=c)if(K(d))a=c,c=G(d),d=K(d);else return c...
  function a (line 103) | function a(c,f,g){var h=null;if(2<arguments.length){for(var h=0,l=Array(...
  function b (line 103) | function b(a,c,d){for(;;)if(a>c)if(K(d))a=c,c=G(d),d=K(d);else return c>...
  function a (line 104) | function a(c,f,g){var h=null;if(2<
  function b (line 105) | function b(a,c,d){for(;;)if(a>=c)if(K(d))a=c,c=G(d),d=K(d);else return c...
  function Cd (line 106) | function Cd(a,b){var c=(a-a%b)/b;return 0<=c?Math.floor.b?Math.floor.b(c...
  function Dd (line 106) | function Dd(a){a-=a>>1&1431655765;a=(a&858993459)+(a>>2&858993459);retur...
  function Ed (line 107) | function Ed(a){var b=1;for(a=D(a);;)if(a&&0<b)b-=1,a=K(a);else return a}
  function a (line 108) | function a(a){return null==a?"":da(a)}
  function a (line 108) | function a(b,d){var h=null;if(1<arguments.length){for(var h=0,l=Array(ar...
  function c (line 108) | function c(a,d){for(var e=new fa(b.b(a)),l=d;;)if(t(l))e=e.append(b.b(G(...
  function Ic (line 109) | function Ic(a,b){var c;if(cd(b))if(Ec(a)&&Ec(b)&&Q(a)!==Q(b))c=!1;else a...
  function Fd (line 110) | function Fd(a,b,c,d,e){this.k=a;this.first=b;this.M=c;this.count=d;this....
  function Hd (line 111) | function Hd(a){this.k=a;this.j=65937614;this.q=8192}
  function Id (line 113) | function Id(a){return a?a.j&134217728||a.xc?!0:a.j?!1:w(Fb,a):w(Fb,a)}
  function Jd (line 113) | function Jd(a){return Id(a)?Gb(a):A.c(Nc,J,a)}
  function a (line 114) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 114) | function b(a){var b;if(a instanceof F&&0===a.m)b=a.e;else a:{for(b=[];;)...
  function Ld (line 115) | function Ld(a,b,c,d){this.k=a;this.first=b;this.M=c;this.p=d;this.j=6592...
  function M (line 116) | function M(a,b){var c=null==b;return(c?c:b&&(b.j&64||b.jb))?new Ld(null,...
  function Md (line 117) | function Md(a,b){if(a.pa===b.pa)return 0;var c=Aa(a.ba);if(t(c?b.ba:c))r...
  function U (line 117) | function U(a,b,c,d){this.ba=a;this.name=b;this.pa=c;this.Ya=d;this.j=215...
  function Nd (line 119) | function Nd(a,b){return a===b?!0:a instanceof U&&b instanceof U?a.pa===b...
  function a (line 120) | function a(a,b){return new U(a,b,[z(t(a)?[z(a),z("/")].join(""):null),z(...
  function b (line 120) | function b(a){if(a instanceof U)return a;if(a instanceof qc){var b;if(a&...
  function V (line 121) | function V(a,b,c,d){this.k=a;this.cb=b;this.C=c;this.p=d;this.q=0;this.j...
  function Qd (line 121) | function Qd(a){null!=a.cb&&(a.C=a.cb.l?a.cb.l():a.cb.call(null),a.cb=nul...
  function Rd (line 123) | function Rd(a,b){this.Ab=a;this.end=b;this.q=0;this.j=2}
  function Td (line 123) | function Td(a){return new Rd(Array(a),0)}
  function Sd (line 123) | function Sd(a,b,c){this.e=a;this.V=b;this.end=c;this.q=0;this.j=524306}
  function a (line 125) | function a(a,b,c){return new Sd(a,b,c)}
  function b (line 125) | function b(a,b){return new Sd(a,b,a.length)}
  function c (line 125) | function c(a){return new Sd(a,0,a.length)}
  function Vd (line 125) | function Vd(a,b,c,d){this.ca=a;this.ra=b;this.k=c;this.p=d;this.j=318507...
  function Wd (line 127) | function Wd(a,b){return 0===Ma(a)?b:new Vd(a,b,null,null)}
  function Xd (line 127) | function Xd(a,b){a.add(b)}
  function rd (line 127) | function rd(a){for(var b=[];;)if(D(a))b.push(G(a)),a=K(a);else return b}
  function Yd (line 127) | function Yd(a,b){if(Ec(a))return Q(a);for(var c=a,d=b,e=0;;)if(0<d&&D(c)...
  function a (line 128) | function a(a,b){return new V(null,function(){var c=D(a);return c?fd(c)?W...
  function b (line 128) | function b(a){return new V(null,function(){return a},null,null)}
  function c (line 128) | function c(){return new V(null,function(){return null},null,null)}
  function a (line 128) | function a(c,d,e){var f=null;if(2<arguments.length){for(var f=0,q=Array(...
  function b (line 129) | function b(a,c,e){return function q(a,b){return new V(null,function(){va...
  function a (line 130) | function a(a,b,c,d){return M(a,M(b,M(c,d)))}
  function b (line 130) | function b(a,b,c){return M(a,M(b,c))}
  function a (line 130) | function a(c,d,e,m,p){var q=null;if(4<arguments.length){for(var q=0,s=Ar...
  function b (line 130) | function b(a,
  function ce (line 132) | function ce(a){return Qb(a)}
  function a (line 133) | function a(){return Ob(Mc)}
  function a (line 133) | function a(c,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function b (line 133) | function b(a,c,d){for(;;)if(a=Pb(a,c),t(d))c=G(d),d=K(d);else return a}
  function a (line 134) | function a(c,f,g,h){var l=null;if(3<arguments.length){for(var l=0,m=Arra...
  function b (line 135) | function b(a,c,d,h){for(;;)if(a=Rb(a,c,d),t(h))c=G(h),d=Lc(h),h=K(K(h));...
  function a (line 136) | function a(c,f,g){var h=null;if(2<arguments.length){for(var h=0,l=Array(...
  function b (line 136) | function b(a,c,d){for(;;)if(a=Sb(a,c),t(d))c=G(d),d=K(d);else return a}
  function a (line 137) | function a(c,f,g){var h=null;if(2<arguments.length){for(var h=0,l=Array(...
  function b (line 137) | function b(a,c,d){for(;;)if(a=Vb(a,c),t(d))c=G(d),d=K(d);
  function he (line 139) | function he(a,b,c){var d=D(c);if(0===b)return a.l?a.l():a.call(null);c=V...
  function a (line 145) | function a(a,b,c,d,e){b=be.n(b,c,d,e);c=a.i;return a.f?(d=Yd(b,c+1),d<=c...
  function b (line 145) | function b(a,b,c,d){b=be.c(b,c,d);c=a.i;return a.f?(d=Yd(b,c+1),d<=c?he(...
  function c (line 145) | function c(a,b,c){b=be.a(b,c);c=a.i;if(a.f){var d=Yd(b,c+1);return d<=c?...
  function d (line 145) | function d(a,b){var c=a.i;if(a.f){var d=Yd(b,c+1);return d<=c?he(a,d,b):...
  function a (line 145) | function a(c,d,e,f,g,u){var v=null;
  function b (line 146) | function b(a,c,d,e,f,g){c=M(c,M(d,M(e,M(f,$d(g)))));d=a.i;return a.f?(e=...
  function a (line 147) | function a(a,b,c,d,e,f){var g=O,v=Vc(a);b=b.r?b.r(v,c,d,e,f):b.call(null...
  function b (line 147) | function b(a,b,c,d,e){var f=O,g=Vc(a);b=b.n?b.n(g,
  function c (line 148) | function c(a,b,c,d){var e=O,f=Vc(a);b=b.c?b.c(f,c,d):b.call(null,f,c,d);...
  function d (line 148) | function d(a,b,c){var d=O,e=Vc(a);b=b.a?b.a(e,c):b.call(null,e,c);return...
  function e (line 148) | function e(a,b){var c=O,d;d=Vc(a);d=b.b?b.b(d):b.call(null,d);return c(a...
  function a (line 148) | function a(c,d,e,f,g,h,y){var B=null;if(6<arguments.length){for(var B=0,...
  function b (line 148) | function b(a,
  function a (line 150) | function a(a,b){return!sc.a(a,b)}
  function a (line 150) | function a(c,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function b (line 150) | function b(a,c,d){return Aa(T.n(sc,a,c,d))}
  function re (line 152) | function re(a,b){this.C=a;this.m=b}
  function se (line 153) | function se(a,b){this.e=a;this.m=b}
  function ve (line 153) | function ve(a,b){this.eb=a;this.Qa=b}
  function we (line 154) | function we(a){if(null==a)return qe();if("string"===typeof a)return new ...
  function xe (line 154) | function xe(a,b){this.fa=a;this.$b=b}
  function ye (line 156) | function ye(a,b){var c=function(){function a(b,c){b.first=c;b.M=new ze(b...
  function Ae (line 156) | function Ae(a,b,c){this.fa=a;this.Kb=b;this.ac=c}
  function a (line 158) | function a(a,b,c){var g=function(){function a(b,c){b.first=c;b.M=new ze(...
  function b (line 158) | function b(a,b){return c.c(a,b,Array(b.length))}
  function ze (line 159) | function ze(a,b,c,d){this.X=a;this.first=b;this.M=c;this.k=d;this.q=0;th...
  function a (line 161) | function a(a){return kd(a)?a:(a=D(a))?a:J}
  function a (line 161) | function a(c,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function b (line 161) | function b(a,c,d){d=rd(M(c,d));c=[];d=D(d);for(var e=null,m=0,p=0;;)if(p...
  function Ee (line 163) | function Ee(a,b){for(;;){if(null==D(b))return!0;var c;c=G(b);c=a.b?a.b(c...
  function Fe (line 163) | function Fe(a,b){for(;;)if(D(b)){var c;c=G(b);c=a.b?a.b(c):a.call(null,c...
  function Ge (line 163) | function Ge(a){if("number"===typeof a&&Aa(isNaN(a))&&Infinity!==a&&parse...
  function He (line 164) | function He(a){return function(){function b(b,c){return Aa(a.a?a.a(b,c):...
  function a (line 166) | function a(a,b,c){return function(){function d(h,l,m){h=c.c?c.c(h,l,m):c...
  function b (line 168) | function b(a,b){return function(){function c(d,g,h){d=b.c?b.c(d,g,h):b.c...
  function a (line 170) | function a(c,d,e,m){var p=null;
  function b (line 171) | function b(a,c,d,e){return function(a){return function(){function b(a){v...
  function a (line 173) | function a(a,b,c,d){return function(){function e(m,p,q){return a.P?a.P(b...
  function b (line 175) | function b(a,b,c){return function(){function d(e,l,m){return a.r?a.r(b,c...
  function c (line 177) | function c(a,b){return function(){function c(d,e,h){return a.n?a.n(b,d,e...
  function a (line 179) | function a(c,d,e,f,q){var s=null;if(4<arguments.length){for(var s=0,u=Ar...
  function b (line 179) | function b(a,c,d,e,f){return function(){function b(a){var c=null;if(0<ar...
  function a (line 181) | function a(a,b,c,d){return function(){function l(l,m,p){l=null==l?b:l;m=...
  function b (line 183) | function b(a,b,c){return function(){function d(h,l,m){h=null==h?b:h;l=nu...
  function c (line 185) | function c(a,b){return function(){function c(d,g,h){d=null==d?b:d;return...
  function a (line 187) | function a(a,b){return new V(null,function(){var f=D(b);if(f){if(fd(f)){...
  function b (line 188) | function b(a){return function(b){return function(){function c(f,g){var h...
  function Me (line 189) | function Me(a){this.state=a;this.q=0;this.j=32768}
  function a (line 190) | function a(a,b){return function g(b,c){return new V(null,function(){var ...
  function b (line 190) | function b(a){return function(b){return function(c){return function(){fu...
  function a (line 192) | function a(a,b,c,d){return new V(null,function(){var f=D(b),q=D(c),s=D(d...
  function b (line 192) | function b(a,b,c){return new V(null,function(){var d=D(b),f=D(c);if(d&&f...
  function c (line 193) | function c(a,b){return new V(null,function(){var c=D(b);if(c){if(fd(c)){...
  function d (line 193) | function d(a){return function(b){return function(){function c(d,e){var f...
  function a (line 195) | function a(c,d,e,f,g){var u=null;if(4<arguments.length){for(var u=0,v=Ar...
  function b (line 195) | function b(a,c,d,
  function a (line 197) | function a(a,b){return new V(null,function(){if(0<a){var f=D(b);return f...
  function b (line 197) | function b(a){return function(b){return function(a){return function(){fu...
  function a (line 199) | function a(a,b){return new V(null,function(c){return function(){return c...
  function b (line 199) | function b(a){return function(b){return function(a){return function(){fu...
  function a (line 200) | function a(a,b){return new V(null,function(c){return function(){return c(a,
  function b (line 201) | function b(a){return function(b){return function(c){return function(){fu...
  function a (line 202) | function a(a,b){return Pe.a(a,c.b(b))}
  function b (line 202) | function b(a){return new V(null,function(){return M(a,c.b(a))},null,null)}
  function a (line 203) | function a(a,b){return Pe.a(a,c.b(b))}
  function b (line 203) | function b(a){return new V(null,function(){return M(a.l?a.l():a.call(nul...
  function a (line 203) | function a(a,c){return new V(null,function(){var f=
  function a (line 204) | function a(b,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function c (line 204) | function c(a,d,e){return new V(null,function(){var c=Oe.a(D,Nc.d(e,d,Kc(...
  function a (line 205) | function a(a){return Ie.a(Oe.b(a),Ve)}
  function a (line 205) | function a(c,d){var h=null;if(1<arguments.length){for(var h=0,l=Array(ar...
  function b (line 206) | function b(a,c){return T.a(ae,T.c(Oe,a,c))}
  function a (line 206) | function a(a,b){return new V(null,
  function b (line 207) | function b(a){return function(b){return function(){function c(f,g){retur...
  function a (line 208) | function a(a,b){return Xe.a(He(a),b)}
  function b (line 208) | function b(a){return Xe.b(He(a))}
  function Ze (line 209) | function Ze(a){var b=$e;return function d(a){return new V(null,function(...
  function a (line 210) | function a(a,b,c){return a&&(a.q&4||a.dc)?O(ce(wd.n(b,de,Ob(a),c)),Vc(a)...
  function b (line 210) | function b(a,b){return null!=a?a&&(a.q&4||a.dc)?O(ce(A.c(Pb,Ob(a),b)),Vc...
  function a (line 210) | function a(a,b,c,h){return new V(null,function(){var l=D(h);if(l){var m=...
  function b (line 211) | function b(a,b,c){return new V(null,function(){var h=D(c);if(h){var l=Pe...
  function c (line 211) | function c(a,b){return d.c(a,a,b)}
  function a (line 211) | function a(a,
  function b (line 212) | function b(a,b){return c.c(a,b,null)}
  function a (line 212) | function a(a,b,c,d,f,q){var s=R.c(b,0,null);return(b=Ed(b))?Rc.c(a,s,e.P...
  function b (line 213) | function b(a,b,c,d,f){var q=R.c(b,0,null);return(b=Ed(b))?Rc.c(a,q,e.r(S...
  function c (line 213) | function c(a,b,c,d){var f=R.c(b,0,null);return(b=Ed(b))?Rc.c(a,f,e.n(S.a...
  function d (line 213) | function d(a,b,c){var d=R.c(b,0,null);return(b=Ed(b))?Rc.c(a,d,e.c(S.a(a...
  function a (line 214) | function a(c,d,e,f,g,u,v){var y=null;if(6<arguments.length){for(var y=0,...
  function b (line 214) | function b(a,c,d,f,g,h,v){var y=R.c(c,0,null);return(c=Ed(c))?Rc.c(a,y,T...
  function ef (line 216) | function ef(a,b){this.u=a;this.e=b}
  function ff (line 216) | function ff(a){return new ef(a,[null,null,null,null,null,null,null,null,...
  function gf (line 216) | function gf(a){return new ef(a.u,Fa(a.e))}
  function hf (line 216) | function hf(a){a=a.g;return 32>a?0:a-1>>>5<<5}
  function jf (line 216) | function jf(a,b,c){for(;;){if(0===b)return c;var d=ff(a);d.e[0]=c;c=d;b-...
  function mf (line 217) | function mf(a,b){throw Error([z("No item "),z(a),z(" in vector of length...
  function nf (line 217) | function nf(a,b){if(b>=hf(a))return a.W;for(var c=a.root,d=a.shift;;)if(...
  function of (line 217) | function of(a,b){return 0<=b&&b<a.g?nf(a,b):mf(b,a.g)}
  function tf (line 218) | function tf(a,b,c,d,e,f){this.m=a;this.zb=b;this.e=c;this.oa=d;this.star...
  function W (line 219) | function W(a,b,c,d,e,f){this.k=a;this.g=b;this.shift=c;this.root=d;this....
  function zf (line 229) | function zf(a){return Qb(A.c(Pb,Ob(Mc),a))}
  function a (line 230) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 230) | function b(a){if(a instanceof F&&0===a.m)a:{a=a.e;var b=a.length;if(32>b...
  function Bf (line 231) | function Bf(a,b,c,d,e,f){this.ha=a;this.Ja=b;this.m=c;this.V=d;this.k=e;...
  function a (line 234) | function a(a,b,c,d,l){return new Bf(a,b,c,d,l,null)}
  function b (line 234) | function b(a,b,c,d){return new Bf(a,b,c,d,null,null)}
  function c (line 234) | function c(a,b,c){return new Bf(a,of(a,b),b,c,null,null)}
  function Df (line 235) | function Df(a,b,c,d,e){this.k=a;this.oa=b;this.start=c;this.end=d;this.p...
  function Ef (line 240) | function Ef(a,b,c,d,e){for(;;)if(b instanceof Df)c=b.start+c,d=b.start+d...
  function a (line 240) | function a(a,b,c){return Ef(null,a,b,c,null)}
  function b (line 240) | function b(a,b){return c.c(a,b,Q(a))}
  function Ff (line 241) | function Ff(a,b){return a===b.u?b:new ef(a,Fa(b.e))}
  function wf (line 241) | function wf(a){return new ef({},Fa(a.e))}
  function xf (line 241) | function xf(a){var b=[null,null,null,null,null,null,null,null,null,null,...
  function vf (line 242) | function vf(a,b,c,d){this.g=a;this.shift=b;this.root=c;this.W=d;this.j=2...
  function Kf (line 249) | function Kf(a,b,c,d){this.k=a;this.ea=b;this.sa=c;this.p=d;this.q=0;this...
  function Lf (line 251) | function Lf(a,b,c,d,e){this.k=a;this.count=b;this.ea=c;this.sa=d;this.p=...
  function Nf (line 253) | function Nf(){this.q=0;this.j=2097152}
  function Pf (line 253) | function Pf(a,b){return md(dd(b)?Q(a)===Q(b)?Ee(ud,Oe.a(function(a){retu...
  function Qf (line 254) | function Qf(a,b){var c=a.e;if(b instanceof U)a:{for(var d=c.length,e=b.p...
  function Rf (line 255) | function Rf(a,b,c){this.e=a;this.m=b;this.Z=c;this.q=0;this.j=32374990}
  function Sf (line 257) | function Sf(a,b,c){this.e=a;this.m=b;this.g=c}
  function pa (line 257) | function pa(a,b,c,d){this.k=a;this.g=b;this.e=c;this.p=d;this.j=16647951...
  function Tf (line 264) | function Tf(a,b,c){this.Va=a;this.qa=b;this.e=c;this.q=56;this.j=258}
  function Xf (line 267) | function Xf(a,b){for(var c=Ob(Qc),d=0;;)if(d<a)c=ee.c(c,b[d],b[d+1]),d+=...
  function $f (line 267) | function $f(){this.o=!1}
  function ag (line 268) | function ag(a,b){return a===b?!0:Nd(a,b)?!0:sc.a(a,b)}
  function a (line 268) | function a(a,b,c,g,h){a=Fa(a);a[b]=c;a[g]=h;return a}
  function b (line 268) | function b(a,b,c){a=Fa(a);a[b]=c;return a}
  function cg (line 268) | function cg(a,b){var c=Array(a.length-2);hd(a,0,c,0,2*b);hd(a,2*(b+1),c,...
  function a (line 269) | function a(a,b,c,g,h,l){a=a.Na(b);a.e[c]=g;a.e[h]=l;return a}
  function b (line 269) | function b(a,b,c,g){a=a.Na(b);a.e[c]=g;return a}
  function eg (line 270) | function eg(a,b,c){for(var d=a.length,e=0,f=c;;)if(e<d){c=a[e];if(null!=...
  function fg (line 270) | function fg(a,b,c){this.u=a;this.w=b;this.e=c}
  function gg (line 271) | function gg(a,b,c,d){if(a.w===c)return null;a=a.Na(b);b=a.e;var e=b.leng...
  function lg (line 278) | function lg(a,b,c){var d=a.e,e=d.length;a=Array(2*(a.g-1));for(var f=0,g...
  function jg (line 278) | function jg(a,b,c){this.u=a;this.g=b;this.e=c}
  function ng (line 281) | function ng(a,b,c){b*=2;for(var d=0;;)if(d<b){if(ag(c,a[d]))return d;d+=...
  function og (line 281) | function og(a,b,c,d){this.u=a;this.Ia=b;this.g=c;this.e=d}
  function a (line 285) | function a(a,b,c,g,h,l,m){var p=nc(c);if(p===h)return new og(null,p,2,[c...
  function b (line 285) | function b(a,b,c,g,h,l){var m=nc(b);if(m===g)return new og(null,m,2,[b,c...
  function pg (line 286) | function pg(a,b,c,d,e){this.k=a;this.Pa=b;this.m=c;this.C=d;this.p=e;thi...
  function a (line 288) | function a(a,b,c){if(null==c)for(c=a.length;;)if(b<c){if(null!=a[b])retu...
  function b (line 288) | function b(a){return c.c(a,0,null)}
  function qg (line 289) | function qg(a,b,c,d,e){this.k=a;this.Pa=b;this.m=c;this.C=d;this.p=e;thi...
  function a (line 291) | function a(a,b,c,g){if(null==g)for(g=b.length;;)if(c<g){var h=b[c];if(t(...
  function b (line 291) | function b(a){return c.n(null,a,0,null)}
  function rg (line 292) | function rg(a,b,c,d,e,f){this.k=a;this.g=b;this.root=c;this.U=d;this.da=...
  function sg (line 297) | function sg(a,b,c,d,e){this.u=a;this.root=b;this.count=c;this.U=d;this.d...
  function ug (line 299) | function ug(a,b){if(a.u){if(b?b.j&2048||b.jc||(b.j?0:w(fb,b)):w(fb,b))re...
  function tg (line 300) | function tg(a,b,c){if(a.u){if(null==b)a.da!==c&&(a.da=c),a.U||(a.count+=...
  function vg (line 300) | function vg(a,b,c){for(var d=b;;)if(null!=a)b=c?a.left:a.right,d=Nc.a(d,...
  function wg (line 300) | function wg(a,b,c,d,e){this.k=a;this.stack=b;this.pb=c;this.g=d;this.p=e...
  function xg (line 302) | function xg(a,b,c){return new wg(null,vg(a,null,b),b,c,null)}
  function yg (line 303) | function yg(a,b,c,d){return c instanceof X?c.left instanceof X?new X(c.k...
  function zg (line 304) | function zg(a,b,c,d){return d instanceof X?d.right instanceof X?new X(d....
  function Ag (line 305) | function Ag(a,b,c,d){if(c instanceof X)return new X(a,b,c.ua(),d,null);i...
  function Z (line 306) | function Z(a,b,c,d,e){this.key=a;this.o=b;this.left=c;this.right=d;this....
  function X (line 311) | function X(a,b,c,d,e){this.key=a;this.o=b;this.left=c;this.right=d;this....
  function Lg (line 320) | function Lg(a,b,c,d,e){this.aa=a;this.na=b;this.g=c;this.k=d;this.p=e;th...
  function Mg (line 321) | function Mg(a,b){for(var c=a.na;;)if(null!=c){var d;d=c.key;d=a.aa.a?a.a...
  function a (line 326) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 326) | function b(a){a=D(a);for(var b=Ob(Qc);;)if(a){var e=K(K(a)),b=ee.c(b,G(a...
  function a (line 326) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 327) | function b(a){a:{a=T.a(Ha,a);for(var b=a.length,e=0,f=Ob(Uf);;)if(e<b)va...
  function a (line 327) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 327) | function b(a){a=D(a);for(var b=Ng;;)if(a){var e=K(K(a)),b=Rc.c(b,G(a),Lc...
  function a (line 328) | function a(a,d){var e=null;if(1<arguments.length){for(var e=0,f=Array(ar...
  function b (line 328) | function b(a,b){for(var e=D(b),f=new Lg(qd(a),null,0,null,0);;)if(e)var ...
  function Sg (line 328) | function Sg(a,b){this.Y=a;this.Z=b;this.q=0;this.j=32374988}
  function Tg (line 330) | function Tg(a){return(a=D(a))?new Sg(a,null):null}
  function Yf (line 330) | function Yf(a){return hb(a)}
  function Ug (line 330) | function Ug(a,b){this.Y=a;this.Z=b;this.q=0;this.j=32374988}
  function Vg (line 332) | function Vg(a){return(a=D(a))?new Ug(a,null):null}
  function Zf (line 332) | function Zf(a){return ib(a)}
  function a (line 333) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 333) | function b(a){return t(Fe(ud,a))?A.a(function(a,b){return Nc.a(t(a)?a:Uf...
  function a (line 333) | function a(a,d){var e=null;if(1<arguments.length){for(var e=0,f=Array(ar...
  function b (line 333) | function b(a,
  function Yg (line 334) | function Yg(a,b){for(var c=Uf,d=D(b);;)if(d)var e=G(d),f=S.c(a,e,Zg),c=j...
  function $g (line 335) | function $g(a,b,c){this.k=a;this.Wa=b;this.p=c;this.j=15077647;this.q=8196}
  function ah (line 338) | function ah(a){this.ma=a;this.j=259;this.q=136}
  function a (line 338) | function a(a,b,c){return $a.c(this.ma,b,jd)===jd?c:b}
  function b (line 338) | function b(a,b){return $a.c(this.ma,b,jd)===jd?null:b}
  function ch (line 339) | function ch(a,b,c){this.k=a;this.ja=b;this.p=c;this.j=417730831;this.q=8...
  function fh (line 343) | function fh(a){a=D(a);if(null==a)return bh;if(a instanceof F&&0===a.m){a...
  function a (line 344) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 344) | function b(a){return A.c(Ra,eh,a)}
  function a (line 344) | function a(a,d){var e=null;if(1<arguments.length){for(var e=0,f=Array(ar...
  function b (line 344) | function b(a,b){return A.c(Ra,new ch(null,Rg(a),0),b)}
  function Od (line 345) | function Od(a){if(a&&(a.q&4096||a.lc))return a.name;if("string"===typeof...
  function a (line 346) | function a(a,b,c){return(a.b?a.b(b):a.call(null,b))>(a.b?a.b(c):a.call(n...
  function a (line 346) | function a(b,d,h,l){var m=null;if(3<arguments.length){for(var m=0,p=Arra...
  function c (line 346) | function c(a,d,e,l){return A.c(function(c,d){return b.c(a,c,d)},b.c(a,d,...
  function jh (line 347) | function jh(a){this.e=a}
  function a (line 349) | function a(a,b,c){return new V(null,function(){var h=D(c);return h?M(Pe....
  function b (line 349) | function b(a,b){return d.c(a,a,b)}
  function c (line 349) | function c(a){return function(b){return function(c){return function(){fu...
  function a (line 350) | function a(a,
  function b (line 351) | function b(a){return function(b){return function(){function c(f,g){retur...
  function mh (line 352) | function mh(a,b,c){return function(d){var e=Kb(a);d=Jb(a,d);e=e.a?e.a(d,...
  function a (line 353) | function a(a,b,c,g,h){var l=Ib(a,c,!0);if(t(l)){var m=R.c(l,0,null);retu...
  function b (line 353) | function b(a,b,c){var g=mh(a,b,c),h;a:{h=[Ad,Bd];var l=h.length;if(l<=Vf...
  function oh (line 354) | function oh(a,b,c){this.m=a;this.end=b;this.step=c}
  function ph (line 355) | function ph(a,b,c,d,e){this.k=a;this.start=b;this.end=c;this.step=d;this...
  function a (line 359) | function a(a,b,c){return new ph(null,a,b,c,null)}
  function b (line 359) | function b(a,b){return e.c(a,b,1)}
  function c (line 359) | function c(a){return e.c(0,a,1)}
  function d (line 359) | function d(){return e.c(0,Number.MAX_VALUE,1)}
  function a (line 359) | function a(a,b){return new V(null,function(){var f=
  function b (line 360) | function b(a){return function(b){return function(c){return function(){fu...
  function a (line 361) | function a(a,b){return new V(null,function(){var f=D(b);if(f){var g=G(f)...
  function b (line 362) | function b(a){return function(b){return function(c,g){return function(){...
  function a (line 363) | function a(a,b){for(;;)if(D(b)&&0<a){var c=a-1,g=K(b);a=c;b=g}else retur...
  function b (line 363) | function b(a){for(;;)if(D(a))a=K(a);else return null}
  function a (line 364) | function a(a,b){uh.a(a,b);return b}
  function b (line 364) | function b(a){uh.b(a);return a}
  function wh (line 365) | function wh(a,b,c,d,e,f,g){var h=ma;try{ma=null==ma?null:ma-1;if(null!=m...
  function a (line 366) | function a(a,d){var e=null;if(1<arguments.length){for(var e=0,f=Array(ar...
  function b (line 366) | function b(a,b){for(var e=D(b),f=null,g=0,h=0;;)if(h<g){var l=f.Q(null,h...
  function zh (line 367) | function zh(a){return[z('"'),z(a.replace(RegExp('[\\\\"\b\f\n\r\t]',"g")...
  function a (line 370) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 370) | function b(a){var b=oa();if(Yc(a))b="";else{var e=z,f=new fa;a:{var g=ne...
  function Bh (line 371) | function Bh(a,b,c,d){return wh(c,function(a,c,d){var h=hb(a);b.c?b.c(h,c...
  function a (line 377) | function a(a,d,e){var f=null;if(2<arguments.length){for(var f=0,g=Array(...
  function b (line 377) | function b(a,b,e){return a.k=T.c(b,a.k,e)}
  function Eh (line 378) | function Eh(a){return function(b,c){var d=a.a?a.a(b,c):a.call(null,b,c);...
  function Ve (line 379) | function Ve(a){return function(b){return function(){function c(a,c){retu...
  function a (line 380) | function a(a){return Ce.a(c.l(),a)}
  function b (line 380) | function b(){return function(a){return function(b){return function(){fun...
  function Gh (line 381) | function Gh(a,b){this.fa=a;this.Zb=b;this.q=0;this.j=2173173760}
  function Ih (line 382) | function Ih(a){if(a?a.gc:a)return a.gc(a);var b;b=Ih[n(null==a?null:a)];...
  function Jh (line 382) | function Jh(a){return(a?t(t(null)?null:a.fc)||(a.yb?0:w(Hh,a)):w(Hh,a))?...
  function Nh (line 384) | function Nh(a,b){if(a?a.ec:a)return a.ec(a,b);var c;c=Nh[n(null==a?null:...
  function a (line 385) | function a(a){return b.d(a,Kc([new pa(null,1,[Oh,!1],null)],0))}
  function a (line 385) | function a(c,d){var h=null;if(1<arguments.length){for(var h=0,l=Array(ar...
  function b (line 385) | function b(a,c){var d=kd(c)?T.a(Og,c):c,e=S.a(d,Oh);return function(a,b,...
  function Qh (line 388) | function Qh(a,b){var c=T.c(ih,a,b);return M(c,Ye.a(function(a){return fu...
  function a (line 389) | function a(a,b){return Q(a)<Q(b)?A.c(Nc,b,a):A.c(Nc,a,b)}
  function a (line 389) | function a(c,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function b (line 389) | function b(a,c,d){a=Qh(Q,Nc.d(d,c,Kc([a],0)));return A.c(af,G(a),H(a))}
  function a (line 390) | function a(a,b){for(;;)if(Q(b)<Q(a)){var c=a;a=b;b=c}else return A.c(fun...
  function a (line 390) | function a(b,
  function c (line 391) | function c(a,d,e){a=Qh(function(a){return-Q(a)},Nc.d(e,d,Kc([a],0)));ret...
  function a (line 392) | function a(a,b){return Q(a)<Q(b)?A.c(function(a,c){return nd(b,c)?Xc.a(a...
  function a (line 392) | function a(b,d,h){var l=null;if(2<arguments.length){for(var l=0,m=Array(...
  function c (line 392) | function c(a,d,
  function Uh (line 394) | function Uh(a,b){return A.c(function(b,d){var e=R.c(d,0,null),f=R.c(d,1,...
  function Vh (line 394) | function Vh(a,b){return A.c(function(a,d){var e=Yg(d,b);return Rc.c(a,e,...
  function Wh (line 394) | function Wh(a){return A.c(function(a,c){var d=R.c(c,0,null),e=R.c(c,1,nu...
  function a (line 395) | function a(a,b,c){a=Q(a)<=Q(b)?new W(null,3,5,uf,[a,b,Wh(c)],null):new W...
  function b (line 395) | function b(a,b){if(D(a)&&D(b)){var c=Sh.a(fh(Tg(G(a))),fh(Tg(G(b)))),
  function $e (line 403) | function $e(a){return a instanceof Array||cd(a)}
  function a (line 409) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 409) | function b(a){return af.a?af.a(Mf,a):af.call(null,Mf,a)}
  function a (line 415) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 415) | function b(a){function b(a,c){return c.b?c.b(a):c.call(null,a)}return A....
  function a (line 416) | function a(a,d){var e=null;if(1<arguments.length){for(var e=0,f=Array(ar...
  function b (line 416) | function b(a,b){return function(e){return T.a(a,M.a?M.a(e,b):M.call(null...
  function a (line 417) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 417) | function b(a){return function(){function b(a){var c=null;if(0<arguments....
  function a (line 419) | function a(a){var d=null;if(0<arguments.length){for(var d=0,e=Array(argu...
  function b (line 419) | function b(a){return function(b){var e=function(){function e(a,b){return...
  function b (line 421) | function b(b){if(0<arguments.length)for(var d=0,e=Array(arguments.length...
  function a (line 422) | function a(a,b){return Ph.d(a,Kc([Oh,b],0))}
  function b (line 422) | function b(a){return Ph.b(a)}

FILE: editor/scripts/parser.js
  function assert (line 279) | function assert(condition, message) {
  function isIn (line 284) | function isIn(el, list) {
  function isDecimalDigit (line 287) | function isDecimalDigit(ch) {
  function isHexDigit (line 290) | function isHexDigit(ch) {
  function isOctalDigit (line 293) | function isOctalDigit(ch) {
  function isWhiteSpace (line 297) | function isWhiteSpace(ch) {
  function isLineTerminator (line 301) | function isLineTerminator(ch) {
  function isIdentifierStart (line 305) | function isIdentifierStart(ch) {
  function isIdentifierPart (line 308) | function isIdentifierPart(ch) {
  function isFutureReservedWord (line 312) | function isFutureReservedWord(id) {
  function isStrictModeReservedWord (line 325) | function isStrictModeReservedWord(id) {
  function isRestrictedWord (line 341) | function isRestrictedWord(id) {
  function isKeyword (line 345) | function isKeyword(id) {
  function skipComment (line 374) | function skipComment() {
  function scanHexEscape (line 445) | function scanHexEscape(prefix) {
  function scanUnicodeCodePointEscape (line 458) | function scanUnicodeCodePointEscape() {
  function getEscapedIdentifier (line 484) | function getEscapedIdentifier() {
  function getIdentifier (line 523) | function getIdentifier() {
  function scanIdentifier (line 541) | function scanIdentifier() {
  function scanPunctuator (line 571) | function scanPunctuator() {
  function scanHexLiteral (line 805) | function scanHexLiteral(start) {
  function scanOctalLiteral (line 830) | function scanOctalLiteral(prefix, start) {
  function scanNumericLiteral (line 865) | function scanNumericLiteral() {
  function scanStringLiteral (line 963) | function scanStringLiteral() {
  function scanTemplate (line 1061) | function scanTemplate() {
  function scanTemplateElement (line 1175) | function scanTemplateElement(option) {
  function scanRegExp (line 1187) | function scanRegExp() {
  function isIdentifierName (line 1284) | function isIdentifierName(token) {
  function advanceSlash (line 1287) | function advanceSlash() {
  function advance (line 1338) | function advance() {
  function lex (line 1398) | function lex() {
  function peek (line 1413) | function peek() {
  function lookahead2 (line 1430) | function lookahead2() {
  function peekLineTerminator (line 1869) | function peekLineTerminator() {
  function throwError (line 1873) | function throwError(token, messageFormat) {
  function throwErrorTolerant (line 1900) | function throwErrorTolerant() {
  function throwUnexpected (line 1912) | function throwUnexpected(token) {
  function expect (line 1943) | function expect(value) {
  function expectKeyword (line 1951) | function expectKeyword(keyword) {
  function match (line 1958) | function match(value) {
  function matchKeyword (line 1962) | function matchKeyword(keyword) {
  function matchContextualKeyword (line 1966) | function matchContextualKeyword(keyword) {
  function matchAssign (line 1970) | function matchAssign() {
  function consumeSemicolon (line 1978) | function consumeSemicolon() {
  function isLeftHandSide (line 1998) | function isLeftHandSide(expr) {
  function isAssignableLeftHandSide (line 2001) | function isAssignableLeftHandSide(expr) {
  function parseArrayInitialiser (line 2005) | function parseArrayInitialiser() {
  function parsePropertyFunction (line 2067) | function parsePropertyFunction(options) {
  function parsePropertyMethodFunction (line 2085) | function parsePropertyMethodFunction(options) {
  function parseObjectPropertyKey (line 2102) | function parseObjectPropertyKey() {
  function parseObjectProperty (line 2115) | function parseObjectProperty() {
  function parseObjectInitialiser (line 2169) | function parseObjectInitialiser() {
  function parseTemplateElement (line 2207) | function parseTemplateElement(option) {
  function parseTemplateLiteral (line 2217) | function parseTemplateLiteral() {
  function parseGroupExpression (line 2230) | function parseGroupExpression() {
  function parsePrimaryExpression (line 2239) | function parsePrimaryExpression() {
  function parseArguments (line 2298) | function parseArguments() {
  function parseSpreadOrAssignmentExpression (line 2316) | function parseSpreadOrAssignmentExpression() {
  function parseNonComputedProperty (line 2323) | function parseNonComputedProperty() {
  function parseNonComputedMember (line 2330) | function parseNonComputedMember() {
  function parseComputedMember (line 2334) | function parseComputedMember() {
  function parseNewExpression (line 2341) | function parseNewExpression() {
  function parseLeftHandSideExpressionAllowCall (line 2348) | function parseLeftHandSideExpressionAllowCall() {
  function parseLeftHandSideExpression (line 2365) | function parseLeftHandSideExpression() {
  function parsePostfixExpression (line 2380) | function parsePostfixExpression() {
  function parseUnaryExpression (line 2399) | function parseUnaryExpression() {
  function binaryPrecedence (line 2432) | function binaryPrecedence(token, allowIn) {
  function parseBinaryExpression (line 2495) | function parseBinaryExpression() {
  function parseConditionalExpression (line 2537) | function parseConditionalExpression() {
  function reinterpretAsAssignmentBindingPattern (line 2553) | function reinterpretAsAssignmentBindingPattern(expr) {
  function reinterpretAsDestructuredParameter (line 2587) | function reinterpretAsDestructuredParameter(options, expr) {
  function reinterpretAsCoverFormalsList (line 2614) | function reinterpretAsCoverFormalsList(expressions) {
  function parseArrowFunctionExpression (line 2659) | function parseArrowFunctionExpression(options) {
  function parseAssignmentExpression (line 2676) | function parseAssignmentExpression() {
  function parseExpression (line 2720) | function parseExpression() {
  function parseStatementList (line 2760) | function parseStatementList() {
  function parseBlock (line 2774) | function parseBlock() {
  function parseVariableIdentifier (line 2782) | function parseVariableIdentifier() {
  function parseVariableDeclaration (line 2791) | function parseVariableDeclaration(kind) {
  function parseVariableDeclarationList (line 2818) | function parseVariableDeclarationList(kind) {
  function parseVariableStatement (line 2829) | function parseVariableStatement() {
  function parseConstLetDeclaration (line 2840) | function parseConstLetDeclaration(kind) {
  function parseModuleDeclaration (line 2848) | function parseModuleDeclaration() {
  function parseExportBatchSpecifier (line 2877) | function parseExportBatchSpecifier() {
  function parseExportSpecifier (line 2881) | function parseExportSpecifier() {
  function parseExportDeclaration (line 2890) | function parseExportDeclaration() {
  function parseImportDeclaration (line 2931) | function parseImportDeclaration() {
  function parseImportSpecifier (line 2961) | function parseImportSpecifier() {
  function parseEmptyStatement (line 2971) | function parseEmptyStatement() {
  function parseExpressionStatement (line 2976) | function parseExpressionStatement() {
  function parseIfStatement (line 2982) | function parseIfStatement() {
  function parseDoWhileStatement (line 2998) | function parseDoWhileStatement() {
  function parseWhileStatement (line 3014) | function parseWhileStatement() {
  function parseForVariableDeclaration (line 3026) | function parseForVariableDeclaration() {
  function parseForStatement (line 3030) | function parseForStatement(opts) {
  function parseContinueStatement (line 3106) | function parseContinueStatement() {
  function parseBreakStatement (line 3137) | function parseBreakStatement() {
  function parseReturnStatement (line 3168) | function parseReturnStatement() {
  function parseWithStatement (line 3192) | function parseWithStatement() {
  function parseSwitchCase (line 3205) | function parseSwitchCase() {
  function parseSwitchStatement (line 3227) | function parseSwitchStatement() {
  function parseThrowStatement (line 3260) | function parseThrowStatement() {
  function parseCatchClause (line 3271) | function parseCatchClause() {
  function parseTryStatement (line 3287) | function parseTryStatement() {
  function parseDebuggerStatement (line 3304) | function parseDebuggerStatement() {
  function parseStatement (line 3310) | function parseStatement() {
  function parseConciseBody (line 3380) | function parseConciseBody() {
  function parseFunctionSourceElements (line 3386) | function parseFunctionSourceElements() {
  function validateParam (line 3440) | function validateParam(options, param, name) {
  function parseParam (line 3465) | function parseParam(options) {
  function parseParams (line 3504) | function parseParams(firstRestricted) {
  function parseFunctionDeclaration (line 3529) | function parseFunctionDeclaration() {
  function parseFunctionExpression (line 3576) | function parseFunctionExpression() {
  function parseYieldExpression (line 3625) | function parseYieldExpression() {
  function parseMethodDefinition (line 3645) | function parseMethodDefinition(existingPropNames) {
  function parseClassElement (line 3709) | function parseClassElement(existingProps) {
  function parseClassBody (line 3716) | function parseClassBody() {
  function parseClassExpression (line 3733) | function parseClassExpression() {
  function parseClassDeclaration (line 3748) | function parseClassDeclaration() {
  function matchModuleDeclaration (line 3762) | function matchModuleDeclaration() {
  function parseSourceElement (line 3770) | function parseSourceElement() {
  function parseProgramElement (line 3793) | function parseProgramElement() {
  function parseProgramElements (line 3807) | function parseProgramElements() {
  function parseModuleElement (line 3841) | function parseModuleElement() {
  function parseModuleElements (line 3844) | function parseModuleElements() {
  function parseModuleBlock (line 3858) | function parseModuleBlock() {
  function parseProgram (line 3865) | function parseProgram() {
  function addComment (line 3874) | function addComment(type, value, start, end, loc) {
  function scanComment (line 3895) | function scanComment() {
  function filterCommentLocation (line 4013) | function filterCommentLocation() {
  function collectToken (line 4031) | function collectToken() {
  function collectRegex (line 4061) | function collectRegex() {
  function filterTokenLocation (line 4098) | function filterTokenLocation() {
  function LocationMarker (line 4116) | function LocationMarker() {
  function createLocationMarker (line 4187) | function createLocationMarker() {
  function trackGroupExpression (line 4190) | function trackGroupExpression() {
  function trackLeftHandSideExpression (line 4201) | function trackLeftHandSideExpression() {
  function trackLeftHandSideExpressionAllowCall (line 4223) | function trackLeftHandSideExpressionAllowCall() {
  function filterGroup (line 4250) | function filterGroup(node) {
  function wrapTrackingFunction (line 4265) | function wrapTrackingFunction(range, loc) {
  function patch (line 4339) | function patch() {
  function unpatch (line 4446) | function unpatch() {
  function extend (line 4502) | function extend(object, properties) {
  function tokenize (line 4516) | function tokenize(code, options) {
  function blockAllowed (line 4605) | function blockAllowed(toks, start, inExprDelim, parentIsBlock) {
  function snapshotParserState (line 4728) | function snapshotParserState() {
  function restoreParserState (line 4735) | function restoreParserState(prevState) {
  function suppressReadError (line 4740) | function suppressReadError(func) {
  function makeIdentifier (line 4752) | function makeIdentifier(value, opts) {
  function makePunctuator (line 4773) | function makePunctuator(value, opts) {
  function makeStringLiteral (line 4786) | function makeStringLiteral(value, opts) {
  function makeNumericLiteral (line 4800) | function makeNumericLiteral(value, opts) {
  function makeRegExp (line 4813) | function makeRegExp(value, opts) {
  function makeDelimiter (line 4827) | function makeDelimiter(value, inner) {
  method source (line 4855) | get source() {
  method index (line 4858) | get index() {
  method index (line 4861) | set index(x) {
  method length (line 4864) | get length() {
  method length (line 4867) | set length(x) {
  method lineNumber (line 4870) | get lineNumber() {
  method lineNumber (line 4873) | set lineNumber(x) {
  method lineStart (line 4876) | get lineStart() {
  method lineStart (line 4879) | set lineStart(x) {
  method extra (line 4882) | get extra() {
  function readToken (line 4914) | function readToken(toks, inExprDelim, parentIsBlock) {
  function readDelim (line 5017) | function readDelim(toks, inExprDelim, parentIsBlock) {
  function setReadtable (line 5069) | function setReadtable(readtable, syn) {
  function currentReadtable (line 5079) | function currentReadtable() {
  function read (line 5083) | function read(code) {
  function parse (line 5119) | function parse(code, options) {

FILE: editor/scripts/patterns.js
  function freeVarsInPattern (line 29) | function freeVarsInPattern(pattern) {
  function typeIsLiteral (line 40) | function typeIsLiteral(type) {
  function containsPatternVar (line 43) | function containsPatternVar(patterns) {
  function delimIsSeparator (line 51) | function delimIsSeparator(delim) {
  function isPatternVar (line 54) | function isPatternVar(stx) {
  function joinRepeatedMatch (line 58) | function joinRepeatedMatch(tojoin, punc) {
  function takeLineContext (line 68) | function takeLineContext(from, to) {
  function takeLine (line 74) | function takeLine(from, to) {
  function reversePattern (line 156) | function reversePattern(patterns) {
  function loadLiteralGroup (line 170) | function loadLiteralGroup(patterns) {
  function patternToObject (line 181) | function patternToObject(pat) {
  function isPrimaryClass (line 191) | function isPrimaryClass(name) {
  function loadPattern (line 201) | function loadPattern(patterns, reverse) {
  function cachedTermMatch (line 278) | function cachedTermMatch(stx, term) {
  function expandWithMacro (line 291) | function expandWithMacro(macroName, stx, context, rec) {
  function matchPatternClass (line 338) | function matchPatternClass(patternObj, stx, context) {
  function matchPatterns (line 386) | function matchPatterns(patterns, stx, context, topLevel) {
  function matchPattern (line 536) | function matchPattern(pattern, stx, context, patternEnv, topLevel) {
  function initPatternEnv (line 627) | function initPatternEnv(toEnv, fromEnv, topLevel) {
  function loadPatternEnv (line 639) | function loadPatternEnv(toEnv, fromEnv, topLevel, repeat, prefix) {
  function matchLookbehind (line 661) | function matchLookbehind(patterns, stx, terms, context) {
  function hasMatch (line 711) | function hasMatch(m) {
  function transcribe (line 720) | function transcribe(macroBody, macroNameStx, env) {
  function cloneMatch (line 851) | function cloneMatch(oldMatch) {
  function makeIdentityRule (line 864) | function makeIdentityRule(pattern, isInfix, context) {

FILE: editor/scripts/require.js
  function D (line 7) | function D(b){return M.call(b)==="[object Function]"}
  function E (line 7) | function E(b){return M.call(b)==="[object Array]"}
  function t (line 7) | function t(b,c){if(b){var d;for(d=0;d<b.length;d+=1)if(b[d]&&c(b[d],d,b)...
  function N (line 7) | function N(b,c){if(b){var d;for(d=b.length-1;d>-1;d-=1)if(b[d]&&c(b[d],d...
  function A (line 7) | function A(b,c){for(var d in b)if(b.hasOwnProperty(d)&&c(b[d],d))break}
  function O (line 7) | function O(b,c,d,g){c&&A(c,function(c,j){if(d||!F.call(b,j))g&&typeof c!...
  function r (line 7) | function r(b,c){return function(){return c.apply(b,
  function X (line 8) | function X(b){if(!b)return b;var c=W;t(b.split("."),function(b){c=c[b]})...
  function G (line 8) | function G(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"...
  function ba (line 8) | function ba(){if(H&&H.readyState==="interactive")return H;N(document.get...
  function c (line 10) | function c(a,
  function d (line 12) | function d(a){v&&t(document.getElementsByTagName("script"),function(f){i...
  function p (line 12) | function p(a){var f=k.paths[a];if(f&&E(f)&&f.length>1)return d(a),f.shif...
  function i (line 12) | function i(a){var f,
  function j (line 13) | function j(a,f,b,e){var m,K,d=null,g=f?f.name:null,j=a,l=!0,k="";a||(l=!...
  function n (line 13) | function n(a){var f=
  function q (line 14) | function q(a,f,b){var e=a.id,m=l[e];if(F.call(o,e)&&(!m||m.defineEmitCom...
  function z (line 14) | function z(a,f){var b=a.requireModules,e=!1;if(f)f(a);else if(t(b,functi...
  function s (line 14) | function s(){P.length&&(fa.apply(C,[C.length-1,0].concat(P)),P=[])}
  function u (line 14) | function u(a,f,b){var e=a.map.id;a.error?a.emit("error",a.error):(f[e]=!...
  function w (line 15) | function w(){var a,f,b,e,m=(b=k.waitSeconds*1E3)&&h.startTime+b<(new Dat...
  function y (line 16) | function y(a){n(j(a[0],null,!0)).init(a[1],a[2])}
  function B (line 16) | function B(a){var a=a.currentTarget||a.srcElement,b=h.onScriptLoad;a.det...
  function I (line 16) | function I(){var a;for(s();C.length;)if(a=C.shift(),a[0]===
  function d (line 27) | function d(e,c,i){var k,p;if(f.enableBuildCallback&&c&&D(c))c.__requireJ...

FILE: editor/scripts/stxcase.js
  method function (line 2) | function(stx) {
  method function (line 23) | function(stx) {
  method function (line 73) | function(stx, context) {
  method function (line 412) | function(stx) {
  method $name (line 676) | $name (true) $rhs

FILE: editor/scripts/sweet.js
  function makeExpand (line 67) | function makeExpand(expandFn) {
  function expandSyntax (line 106) | function expandSyntax(stx, modules, options) {
  function parse (line 128) | function parse(code, modules, options) {
  function compile (line 139) | function compile(code, options) {
  function setReadtable (line 173) | function setReadtable(readtableModule) {
  function currentReadtable (line 178) | function currentReadtable() {
  function loadNodeModule (line 181) | function loadNodeModule(root, moduleName, options) {
  function optimizeHygiene (line 198) | function optimizeHygiene(ast) {
  function loadMacro (line 269) | function loadMacro(relative_file) {

FILE: editor/scripts/syntax.js
  function assert (line 15) | function assert(condition, message) {
  function Rename (line 27) | function Rename(id, name, ctx, defctx) {
  function Mark (line 36) | function Mark(mark, ctx) {
  function Def (line 41) | function Def(defctx, ctx) {
  function Syntax (line 46) | function Syntax(token, oldstx) {
  function applyContext (line 92) | function applyContext(stxCtx, ctx) {
  function syntaxFromToken (line 129) | function syntaxFromToken(token, oldstx) {
  function mkSyntax (line 132) | function mkSyntax(stx, value, type, inner) {
  function makeValue (line 191) | function makeValue(val, stx) {
  function makeRegex (line 218) | function makeRegex(val, flags, stx) {
  function makeIdent (line 224) | function makeIdent(val, stx) {
  function makeKeyword (line 227) | function makeKeyword(val, stx) {
  function makePunc (line 230) | function makePunc(val, stx) {
  function makeDelim (line 233) | function makeDelim(val, inner, stx) {
  function unwrapSyntax (line 236) | function unwrapSyntax(stx) {
  function syntaxToTokens (line 252) | function syntaxToTokens(stx) {
  function tokensToSyntax (line 261) | function tokensToSyntax(tokens) {
  function joinSyntax (line 273) | function joinSyntax(tojoin, punc) {
  function joinSyntaxArray (line 286) | function joinSyntaxArray(tojoin, punc) {
  function cloneSyntax (line 299) | function cloneSyntax(stx) {
  function cloneSyntaxArray (line 302) | function cloneSyntaxArray(arr) {
  function MacroSyntaxError (line 311) | function MacroSyntaxError(name, message, stx) {
  function throwSyntaxError (line 316) | function throwSyntaxError(name, message, stx) {
  function SyntaxCaseError (line 322) | function SyntaxCaseError(message) {
  function throwSyntaxCaseError (line 325) | function throwSyntaxCaseError(message) {
  function printSyntaxError (line 328) | function printSyntaxError(code, err) {
  function prettyPrint (line 359) | function prettyPrint(stxarr, shouldResolve) {

FILE: macros/index.js
  method function (line 295) | function $name() {
  method _sexpr (line 361) | _sexpr (truthy $sexpr)
  method _sexpr (line 368) | _sexpr (truthy $sexpr)
  method _sexpr (line 469) | _sexpr (threadf ($fn $v $args ...) $x ...)

FILE: test/core.js
  method "a" (line 274) | "a" (inc 1) (str "b") 4} (hashMap "a" 2 "b" 4))).to.eql(true);
  method function (line 326) | function() {
  method function (line 350) | function() {
  method function (line 404) | function() {
Condensed preview — 38 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,573K chars).
[
  {
    "path": ".gitignore",
    "chars": 57,
    "preview": ".DS_Store\n\nnode_modules\nnpm-debug.log\n\n/test/core.out.js\n"
  },
  {
    "path": "Gruntfile.js",
    "chars": 4776,
    "preview": "module.exports = function(grunt) {\n  grunt.initConfig({\n    mochaTest: {\n      test: {\n        options: {\n          repo"
  },
  {
    "path": "LICENSE",
    "chars": 1080,
    "preview": "Copyright (C) 2014 Luca Antiga http://lantiga.github.io\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "README.md",
    "chars": 2482,
    "preview": "\n# ki\n\n**lisp + mori, sweet.js**\n\n![ki](http://ki-lang.org/images/ki-color.svg)\n\nSee [ki-lang.org](http://ki-lang.org) f"
  },
  {
    "path": "bin/ki",
    "chars": 231,
    "preview": "#!/usr/bin/env node\n\nvar path = require('path');\nvar fs = require('fs');\nvar lib = path.join(path.dirname(fs.realpathSyn"
  },
  {
    "path": "editor/addon/runmode.js",
    "chars": 1649,
    "preview": "CodeMirror.runMode = function(string, modespec, callback, options) {\n  var mode = CodeMirror.getMode(CodeMirror.defaults"
  },
  {
    "path": "editor/codemirror.css",
    "chars": 5802,
    "preview": "/* BASICS */\n\n.CodeMirror {\n  /* Set height, width, borders, and global font properties here */\n  font-family: monospace"
  },
  {
    "path": "editor/editor.html",
    "chars": 2781,
    "preview": "<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Try ki</title>\n  <script src=\"scripts/jquery.js\"></script>\n  <script src"
  },
  {
    "path": "editor/index.html",
    "chars": 125,
    "preview": "<html>\n  <head>\n    <script data-main=\"scripts/main\" src=\"scripts/require.js\"></script>\n  </head>\n  <body>\n  </body>\n</h"
  },
  {
    "path": "editor/mode/javascript/javascript.js",
    "chars": 14424,
    "preview": "// TODO actually recognize syntax of TypeScript constructs\n\nCodeMirror.defineMode(\"javascript\", function(config, parserC"
  },
  {
    "path": "editor/mode/runmode.js",
    "chars": 1649,
    "preview": "CodeMirror.runMode = function(string, modespec, callback, options) {\n  var mode = CodeMirror.getMode(CodeMirror.defaults"
  },
  {
    "path": "editor/scripts/codemirror.js",
    "chars": 223431,
    "preview": "// CodeMirror version 3.14\n//\n// CodeMirror is the only global var we claim\nwindow.CodeMirror = (function() {\n  \"use str"
  },
  {
    "path": "editor/scripts/editor.js",
    "chars": 2867,
    "preview": "requirejs.config({\n    shim: {\n        'underscore': {\n            exports: '_'\n        }\n    }\n});\n\nrequire([\"./ki\", \"t"
  },
  {
    "path": "editor/scripts/escodegen.js",
    "chars": 148838,
    "preview": "// Generated by CommonJS Everywhere 0.8.1\n(function (global) {\n  function require(file, parentModule) {\n    if ({}.hasOw"
  },
  {
    "path": "editor/scripts/escope.js",
    "chars": 38381,
    "preview": "/*\n  Copyright (C) 2012-2013 Yusuke Suzuki <utatane.tea@gmail.com>\n  Copyright (C) 2013 Alex Seville <hi@alexandersevill"
  },
  {
    "path": "editor/scripts/estraverse.js",
    "chars": 21790,
    "preview": "/*\n  Copyright (C) 2012-2013 Yusuke Suzuki <utatane.tea@gmail.com>\n  Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gma"
  },
  {
    "path": "editor/scripts/expander.js",
    "chars": 114093,
    "preview": "/*\n  Copyright (C) 2012 Tim Disney <tim@disnet.me>\n\n\n  Redistribution and use in source and binary forms, with or withou"
  },
  {
    "path": "editor/scripts/jquery.js",
    "chars": 242142,
    "preview": "/*!\n * jQuery JavaScript Library v2.0.3\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Cop"
  },
  {
    "path": "editor/scripts/ki.js",
    "chars": 2989,
    "preview": "\n(function (root, factory) {\n  if (typeof exports === 'object') {\n    factory(exports, require('sweet.js'));\n  }\n  else "
  },
  {
    "path": "editor/scripts/ki.sjs",
    "chars": 22493,
    "preview": "/**\n * ki: the lisp that macroexpands to JavaScript\n * MIT license http://www.opensource.org/licenses/mit-license.php/\n "
  },
  {
    "path": "editor/scripts/main.js",
    "chars": 301,
    "preview": "\nrequirejs.config({\n  shim: {\n    'underscore': {\n      exports: '_'\n    }  \n  }\n});\n\nrequire(['./ki','text!ki.sjs','./m"
  },
  {
    "path": "editor/scripts/mori.js",
    "chars": 187494,
    "preview": "(function(definition){if(typeof exports===\"object\"){module.exports=definition();}else if(typeof define===\"function\"&&def"
  },
  {
    "path": "editor/scripts/parser.js",
    "chars": 202278,
    "preview": "/*\n  Copyright (C) 2013 Ariya Hidayat <ariya.hidayat@gmail.com>\n  Copyright (C) 2013 Thaddee Tyl <thaddee.tyl@gmail.com>"
  },
  {
    "path": "editor/scripts/patterns.js",
    "chars": 40365,
    "preview": "(function (root, factory) {\n    if (typeof exports === 'object') {\n        // CommonJS\n        factory(exports, require("
  },
  {
    "path": "editor/scripts/require.js",
    "chars": 14423,
    "preview": "/*\n RequireJS 2.1.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n Available via the MIT or new BSD "
  },
  {
    "path": "editor/scripts/scopedEval.js",
    "chars": 559,
    "preview": "// thou shalt not macro expand me...all kinds of hygiene hackary\n// with strings and `with`.\n\n\n(function (root, factory)"
  },
  {
    "path": "editor/scripts/stxcase.js",
    "chars": 35291,
    "preview": "let quoteSyntax = macro {\n    function(stx) {\n        var name_stx = stx[0];\n\n        if (!(stx[1] && stx[1].token && st"
  },
  {
    "path": "editor/scripts/sweet.js",
    "chars": 11849,
    "preview": "/*\n  Copyright (C) 2012 Tim Disney <tim@disnet.me>\n\n  Redistribution and use in source and binary forms, with or without"
  },
  {
    "path": "editor/scripts/syntax.js",
    "chars": 16741,
    "preview": "(function (root, factory) {\n    if (typeof exports === 'object') {\n        // CommonJS\n        factory(exports, require("
  },
  {
    "path": "editor/scripts/text.js",
    "chars": 15464,
    "preview": "/**\n * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n * Available via"
  },
  {
    "path": "editor/scripts/underscore.js",
    "chars": 49419,
    "preview": "//     Underscore.js 1.7.0\n//     http://underscorejs.org\n//     (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Invest"
  },
  {
    "path": "editor/theme/sweetprism.css",
    "chars": 2620,
    "preview": "/* sweetprism theme for codemirror */\n/** \n * Loosely based on:\n * sweetprism.js default theme for JavaScript, CSS and H"
  },
  {
    "path": "lib/ki.js",
    "chars": 2989,
    "preview": "\n(function (root, factory) {\n  if (typeof exports === 'object') {\n    factory(exports, require('sweet.js'));\n  }\n  else "
  },
  {
    "path": "lib/ki_run.js",
    "chars": 4327,
    "preview": "\nvar fs = require('fs');\nvar path = require('path');\nvar sweet = require('sweet.js');\nvar uglify = require('uglify-js');"
  },
  {
    "path": "macros/index.js",
    "chars": 22493,
    "preview": "/**\n * ki: the lisp that macroexpands to JavaScript\n * MIT license http://www.opensource.org/licenses/mit-license.php/\n "
  },
  {
    "path": "package.json",
    "chars": 807,
    "preview": "{\n  \"name\": \"ki\",\n  \"version\": \"0.2.5\",\n  \"description\": \"lisp + mori, sweet.js\",\n  \"repository\": {\n    \"type\": \"git\",\n "
  },
  {
    "path": "src/ki.sjs",
    "chars": 22493,
    "preview": "/**\n * ki: the lisp that macroexpands to JavaScript\n * MIT license http://www.opensource.org/licenses/mit-license.php/\n "
  },
  {
    "path": "test/core.js",
    "chars": 20275,
    "preview": "\nvar expect = require(\"expect.js\");\n\n\ndescribe(\"require core\", function() {\n\n  it(\"should create a _ki object\", function"
  }
]

About this extraction

This page contains the full source code of the lantiga/ki GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 38 files (1.4 MB), approximately 397.5k tokens, and a symbol index with 1317 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!