Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10011)

Unified Diff: chrome_linux64/resources/inspector/CodeMirrorTextEditor.js

Issue 23466010: Roll reference builds to r221697. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/reference_builds/
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome_linux64/resources/inspector/CodeMirrorTextEditor.js
===================================================================
--- chrome_linux64/resources/inspector/CodeMirrorTextEditor.js (revision 221742)
+++ chrome_linux64/resources/inspector/CodeMirrorTextEditor.js (working copy)
@@ -1,7815 +1,1389 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// 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;");
- 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");
-
- // 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");
- // DIVs containing the selection and the actual code
- d.lineDiv = elt("div");
- 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;
- // Helper element to properly size the gutter backgrounds
- var scrollerInner = elt("div", [d.sizer, d.heightForcer, d.gutters], null, "position: relative; min-height: 100%");
- // Provides scrolling
- d.scroller = elt("div", [scrollerInner], "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.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();
- // True when a drag from the editor is active
- d.draggingText = false;
-
- 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.display, cm.doc.height);}, 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 style = keyMap[cm.options.keyMap].style;
- cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
- (style ? " cm-keymap-" + style : "");
- }
-
- 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);
- }
-
- 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(d /* display */, docHeight) {
- var totalHeight = docHeight + paddingVert(d);
- d.sizer.style.minHeight = d.heightForcer.style.top = totalHeight + "px";
- var scrollHeight = Math.max(totalHeight, d.scroller.scrollHeight);
- var needsH = d.scroller.scrollWidth > d.scroller.clientWidth;
- var needsV = scrollHeight > d.scroller.clientHeight;
- 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 (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;
- var updated = updateDisplayInner(cm, changes, viewPort);
- 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);
- }
- updateSelection(cm);
- updateScrollbars(cm.display, cm.doc.height);
-
- 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, viewPort) {
- var display = cm.display, doc = cm.doc;
- if (!display.wrapper.clientWidth) {
- display.showingFrom = display.showingTo = doc.first;
- display.viewOffset = 0;
- return;
- }
-
- // Compute the new visible window
- // If scrollTop is specified, use that to determine which lines
- // to render instead of the current scrollbar position.
- var visible = visibleLines(display, doc, viewPort);
- // 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;});
-
- var focused = document.activeElement;
- if (intactLines < (to - from) * .7) display.lineDiv.style.display = "none";
- patchDisplay(cm, from, to, intact, positionsChangedFrom);
- display.lineDiv.style.display = "";
- if (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;
- display.showingFrom = from; display.showingTo = to;
- startWorker(cm, 100);
-
- 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);
-
- if (visibleLines(display, doc, viewPort).to > to)
- updateDisplayInner(cm, [], viewPort);
- 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)
- if (line.widgets[i].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", [line.widgets[i].node], "CodeMirror-linewidget"));
- positionLineWidget(line.widgets[i], 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;
- 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], isFirst = false;
- if (!widget.above) { isFirst = first; first = false; }
- if (widget.node == n.firstChild) {
- positionLineWidget(widget, n, reuse, dims);
- ++widgetsSeen;
- if (isFirst) reuse.insertBefore(lineElement, n);
- break;
- }
- }
- if (i == line.widgets.length) { isOk = false; break; }
- }
- }
- 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");
- 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
- 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, retTop) {
- var lineObj = getLine(doc, line);
- var lineLen = lineObj.text.length, rVal = retTop ? Infinity : -Infinity;
- function coords(ch) {
- return charCoords(cm, Pos(line, ch), "div", lineObj);
- }
-
- iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
- var leftPos = coords(dir == "rtl" ? to - 1 : from);
- var rightPos = coords(dir == "rtl" ? from : to - 1);
- var left = leftPos.left, right = rightPos.right;
- 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 (fromArg == null && from == 0) left = pl;
- rVal = retTop ? Math.min(rightPos.top, rVal) : Math.max(rightPos.bottom, rVal);
- if (left < pl + 1) left = pl;
- add(left, rightPos.top, right - left, rightPos.bottom);
- });
- return rVal;
- }
-
- if (sel.from.line == sel.to.line) {
- drawForLine(sel.from.line, sel.from.ch, sel.to.ch);
- } else {
- var fromObj = getLine(doc, sel.from.line);
- var cur = fromObj, merged, path = [sel.from.line, sel.from.ch], singleLine;
- while (merged = collapsedSpanAtEnd(cur)) {
- var found = merged.find();
- path.push(found.from.ch, found.to.line, found.to.ch);
- if (found.to.line == sel.to.line) {
- path.push(sel.to.ch);
- singleLine = true;
- break;
- }
- cur = getLine(doc, found.to.line);
- }
-
- // This is a single, merged line
- if (singleLine) {
- for (var i = 0; i < path.length; i += 3)
- drawForLine(path[i], path[i+1], path[i+2]);
- } else {
- var middleTop, middleBot, toObj = getLine(doc, sel.to.line);
- if (sel.from.ch)
- // Draw the first line of selection.
- middleTop = drawForLine(sel.from.line, sel.from.ch, null, false);
- else
- // Simply include it in the middle block.
- middleTop = heightAtLine(cm, fromObj) - display.viewOffset;
-
- if (!sel.to.ch)
- middleBot = heightAtLine(cm, toObj) - display.viewOffset;
- else
- middleBot = drawForLine(sel.to.line, collapsedSpanAtStart(toObj) ? null : 0, sel.to.ch, true);
-
- if (middleTop < middleBot) add(pl, middleTop, null, middleBot);
- }
- }
-
- removeChildrenAndAdd(display.selectionDiv, fragment);
- display.selectionDiv.style.display = "";
- }
-
- // Cursor-blinking
- function restartBlink(cm) {
- var display = cm.display;
- clearInterval(display.blinker);
- var on = true;
- display.cursor.style.visibility = display.otherCursor.style.visibility = "";
- display.blinker = setInterval(function() {
- if (!display.cursor.offsetHeight) return;
- 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) {
- 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) 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) {
- var doc = cm.doc, display = cm.display;
- if (!doc.mode.startState) return true;
- var pos = findStartLine(cm, n), 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) {
- 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;
- }
- return {left: pos < ch ? r.right : r.left,
- right: pos > ch ? r.left : r.right,
- top: r.top, bottom: 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.measure;
- }
- }
-
- function measureLine(cm, line) {
- // First look in the cache
- var measure = findCachedMeasurement(cm, line);
- if (!measure) {
- // Failing that, recompute and store result in cache
- 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);
-
- for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
- var size = getRect(cur);
- var top = Math.max(0, size.top - outer.top), bot = Math.min(size.bottom - outer.top, maxBot);
- 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);
- break;
- }
- }
- if (j == vranges.length) vranges.push(top, bot);
- var right = size.right;
- if (cur.measureRight) right = getRect(cur.measureRight).left;
- data[i] = {left: size.left - outer.left, right: right - outer.left, top: j};
- }
- for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
- var vr = cur.top;
- cur.top = vranges[vr]; cur.bottom = vranges[vr+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).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;
- cm.display.maxLineChanged = true;
- cm.display.lineNumChars = null;
- }
-
- // 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 -= cm.display.viewOffset;
- if (context == "page") {
- var lOff = getRect(cm.display.lineSpace);
- yOff += lOff.top + (window.pageYOffset || (document.documentElement || document.body).scrollTop);
- var xOff = lOff.left + (window.pageXOffset || (document.documentElement || document.body).scrollLeft);
- 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 local coords
- function fromCoordSystem(cm, coords, context) {
- if (context == "div") return coords;
- var left = coords.left, top = coords.top;
- if (context == "page") {
- left -= window.pageXOffset || (document.documentElement || document.body).scrollLeft;
- top -= window.pageYOffset || (document.documentElement || document.body).scrollTop;
- }
- var lineSpaceBox = getRect(cm.display.lineSpace);
- left -= lineSpaceBox.left;
- top -= lineSpaceBox.top;
- if (context == "local" || !context) {
- var editorBox = getRect(cm.display.wrapper);
- left -= editorBox.left;
- top -= editorBox.top;
- }
- return {left: left, top: top};
- }
-
- function charCoords(cm, pos, context, lineObj) {
- if (!lineObj) lineObj = getLine(cm.doc, pos.line);
- return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch), 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);
- if (right) m.left = m.right; else m.right = m.left;
- return intoCoordSystem(cm, lineObj, m, context);
- }
- var order = getOrder(lineObj), ch = pos.ch;
- if (!order) return get(ch);
- var main, other, linedir = order[0].level;
- for (var i = 0; i < order.length; ++i) {
- var part = order[i], rtl = part.level % 2, nb, here;
- if (part.from < ch && part.to > ch) return get(ch, rtl);
- var left = rtl ? part.to : part.from, right = rtl ? part.from : part.to;
- if (left == ch) {
- // IE returns bogus offsets and widths for edges where the
- // direction flips, but only for the side with the lower
- // level. So we try to use the side with the higher level.
- if (i && part.level < (nb = order[i-1]).level) here = get(nb.level % 2 ? nb.from : nb.to - 1, true);
- else here = get(rtl && part.from != part.to ? ch - 1 : ch);
- if (rtl == linedir) main = here; else other = here;
- } else if (right == ch) {
- var nb = i < order.length - 1 && order[i+1];
- if (!rtl && nb && nb.from == nb.to) continue;
- if (nb && part.level < nb.level) here = get(nb.level % 2 ? nb.to - 1 : nb.from);
- else here = get(rtl ? ch : ch - 1, true);
- if (rtl == linedir) main = here; else other = here;
- }
- }
- if (linedir && !ch) other = get(order[0].to - 1);
- if (!main) return other;
- if (other) main.other = other;
- return main;
- }
-
- function PosMaybeOutside(line, ch, outside) {
- var pos = new Pos(line, ch);
- 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 PosMaybeOutside(doc.first, 0, true);
- var lineNo = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
- if (lineNo > last)
- return PosMaybeOutside(doc.first + doc.size - 1, getLine(doc, last).text.length, true);
- 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)
- 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 PosMaybeOutside(lineNo, to, toOutside);
- // Do a binary search between these bounds.
- for (;;) {
- if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
- var after = x - fromX < toX - x, ch = after ? from : to;
- while (isExtendingChar.test(lineObj.text.charAt(ch))) ++ch;
- var pos = PosMaybeOutside(lineNo, ch, after ? fromOutside : toOutside);
- pos.after = after;
- 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,
- 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) {
- 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);
- } 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.selectionChanged) 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)) return false;
- var text = input.value;
- if (text == prevInput && posEq(sel.from, sel.to)) return false;
- // IE enjoys randomly deselecting our input's text when
- // re-focusing. If the selection is gone but the cursor is at the
- // start of the input, that's probably what happened.
- if (ie && text && input.selectionStart === 0) {
- 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[same] == text[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;
- makeChange(cm.doc, {from: from, to: to, text: splitLines(text.slice(same)),
- origin: cm.state.pasteIncoming ? "paste" : "+input"}, "end");
-
- cm.curOp.updateInput = updateInput;
- if (text.length > 1000) 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);
- if (minimal) cm.display.input.value = "-";
- else cm.display.input.value = selected || cm.getSelection();
- if (cm.state.focused) selectInput(cm.display.input);
- } else if (user) cm.display.prevInput = cm.display.input.value = "";
- 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));
- on(d.scroller, "dblclick", operation(cm, e_preventDefault));
- 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; });
-
- function onResize() {
- // Might be a text scaling operation, clear size caches.
- d.cachedCharWidth = d.cachedTextHeight = null;
- clearCaches(cm);
- runInOp(cm, bind(regChange, cm));
- }
- 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 (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 (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) return true;
- if (/\bCodeMirror-(?:line)?widget\b/.test(n.className) ||
- 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) 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) {
- 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;
-
- function doSelect(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;
- var cur = posFromMouse(cm, e);
- if (cur) doSelect(cur);
- 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 onDrop(e) {
- var cm = this;
- if (eventInWidget(cm.display, e) || (cm.options.onDragEvent && cm.options.onDragEvent(cm, addStop(e))))
- return;
- e_preventDefault(e);
- 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 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;
- }
-
- function onDragStart(cm, e) {
- if (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) {
- 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;
- }
- if (safari) {
- if (cm.display.dragImg) {
- img = cm.display.dragImg;
- } else {
- cm.display.dragImg = img;
- img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
- cm.display.wrapper.appendChild(img);
- }
- }
- 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, []);
- }
- 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;
-
- // 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;
- }
- }
- }
-
- var display = cm.display, scroll = display.scroller;
- // 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);
- maps.push(cm.options.keyMap);
- if (cm.options.extraKeys) maps.unshift(cm.options.extraKeys);
- 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);
- }, 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)) return doHandleBinding(cm, b);
- });
- } else {
- handled = lookupKey(name, keymaps, function(b) { return doHandleBinding(cm, b); });
- }
- if (handled == "stop") handled = false;
-
- if (handled) {
- e_preventDefault(e);
- restartBlink(cm);
- if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
- }
- 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);
- }
- 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 (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 (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;
- 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 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 && (!ie || ie_lt9)) {
- clearTimeout(detectingSelectAll);
- var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value), i = 0;
- display.prevInput = " ";
- display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
- var 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 (captureMiddleClick) {
- e_stop(e);
- var mouseup = function() {
- off(window, "mouseup", mouseup);
- setTimeout(rehide, 20);
- };
- on(window, "mouseup", mouseup);
- } else {
- setTimeout(rehide, 50);
- }
- }
-
- // UPDATING
-
- function changeEnd(change) {
- 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) {
- var obj = {
- canceled: false,
- from: change.from,
- to: change.to,
- text: change.text,
- origin: change.origin,
- 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;
- },
- cancel: function() { this.canceled = true; }
- };
- 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);
- 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) {
- var hist = doc.history;
- var event = (type == "undo" ? hist.done : hist.undone).pop();
- if (!event) return;
- hist.dirtyCounter += type == "undo" ? -1 : 1;
-
- var anti = {changes: [], anchorBefore: event.anchorAfter, headBefore: event.headAfter,
- anchorAfter: event.anchorBefore, headAfter: event.headBefore};
- (type == "undo" ? hist.undone : hist.done).push(anti);
-
- for (var i = event.changes.length - 1; i >= 0; --i) {
- var change = event.changes[i];
- change.origin = type;
- 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;
- }
- });
- }
-
- 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 = 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), toClear;
- 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 && m.clearOnEnter) {
- (toClear || (toClear = [])).push(m);
- continue;
- } else 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;
- }
- }
- if (toClear) for (var i = 0; i < toClear.length; ++i) toClear[i].clear();
- }
- return curPos;
- }
- }
-
- // SCROLLING
-
- function scrollCursorIntoView(cm) {
- var coords = scrollPosIntoView(cm, cm.doc.sel.head);
- if (!cm.state.focused) return;
- var display = cm.display, box = getRect(display.sizer), doScroll = null, pTop = paddingTop(cm.display);
- if (coords.top + pTop + box.top < 0) doScroll = true;
- else if (coords.bottom + pTop + 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, pt = paddingTop(display);
- y1 += pt; y2 += pt;
- var screen = display.scroller.clientHeight - scrollerCutOff, screentop = display.scroller.scrollTop, result = {};
- var docBottom = cm.doc.height + paddingVert(display);
- var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10;
- if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1);
- else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen;
-
- 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, 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) 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;
- }
- 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;
- 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), dir, 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.after === false || 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 = {
- 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) {
- this.state.keyMaps.push(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) {
- if (overlays[i].modeSpec == spec) {
- overlays.splice(i, 1);
- this.state.modeGen++;
- regChange(this);
- return;
- }
- }
- }),
-
- indentLine: operation(null, function(n, dir, aggressive) {
- if (typeof dir != "string") {
- 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) {
- var doc = this.doc;
- pos = clipPos(doc, pos);
- var state = getStateBefore(this, pos.line), 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};
- },
-
- getStateAfter: function(line) {
- var doc = this.doc;
- line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
- return getStateBefore(this, line + 1);
- },
-
- 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);
- },
-
- 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("\\b" + cls + "\\b").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 upd = cur.replace(new RegExp("^" + cls + "\\b\\s*|\\s*\\b" + cls + "\\b"), "");
- if (upd == cur) return false;
- line[prop] = upd || 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 + paddingTop(display)) + "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() {
- 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: function(pos, margin) {
- if (typeof pos == "number") pos = Pos(pos, 0);
- if (!pos || pos.line != null) {
- pos = pos ? clipPos(this.doc, pos) : this.doc.sel.head;
- scrollPosIntoView(this, pos, margin);
- } else {
- scrollIntoView(this, pos.left, pos.top - margin, pos.right, pos.bottom + margin);
- }
- },
-
- 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);
- 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("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("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("viewportMargin", 10, function(cm){cm.refresh();}, true);
-
- 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 (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.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");
- },
- 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",
- 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;
- }
- }
- function isModifierKey(event) {
- var name = keyNames[event.keyCode];
- return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
- }
- function keyName(event, noShift) {
- 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.collapsed && 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.getOptions = function(copyWidget) {
- var repl = this.replacedWith;
- return {className: this.className,
- inclusiveLeft: this.inclusiveLeft, inclusiveRight: this.inclusiveRight,
- atomic: this.atomic,
- collapsed: this.collapsed,
- clearOnEnter: this.clearOnEnter,
- replacedWith: copyWidget ? repl && repl.cloneNode(true) : repl,
- readOnly: this.readOnly,
- startStyle: this.startStyle, endStyle: this.endStyle};
- };
-
- 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 (marker.collapsed) sawCollapsedSpans = true;
-
- 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.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();
- };
- SharedTextMarker.prototype.getOptions = function(copyWidget) {
- var inner = this.primary.getOptions(copyWidget);
- inner.shared = true;
- return inner;
- };
-
- 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);
- }
- }
- }
-
- 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.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.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
- // array, which contains alternating fragments of text and CSS
- // classes.
- function runMode(cm, text, mode, state, f) {
- var flattenSpans = mode.flattenSpans;
- if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
- var curText = "", curStyle = null;
- var stream = new StringStream(text, cm.options.tabSize);
- if (text == "" && mode.blankLine) mode.blankLine(state);
- while (!stream.eol()) {
- var style = mode.token(stream, state);
- if (stream.pos > 5000) {
- flattenSpans = false;
- // Webkit seems to refuse to render text nodes longer than 57444 characters
- stream.pos = Math.min(text.length, stream.start + 50000);
- style = null;
- }
- var substr = stream.current();
- stream.start = stream.pos;
- if (!flattenSpans || curStyle != style) {
- if (curText) f(curText, curStyle);
- curText = substr; curStyle = style;
- } else curText = curText + substr;
- }
- if (curText) f(curText, curStyle);
- }
-
- function highlightLine(cm, line, state) {
- // A styles array always starts with a number identifying the
- // mode/overlays that it is based on (for easy invalidation).
- var st = [cm.state.modeGen];
- // Compute the base array of styles
- runMode(cm, line.text, cm.doc.mode, state, function(txt, style) {st.push(txt, style);});
-
- // Run overlays, adjust style array.
- for (var o = 0; o < cm.state.overlays.length; ++o) {
- var overlay = cm.state.overlays[o], i = 1;
- runMode(cm, line.text, overlay.mode, true, function(txt, style) {
- var start = i, len = txt.length;
- // Ensure there's a token end at the current position, and that i points at it
- while (len) {
- var cur = st[i], len_ = cur.length;
- if (len_ <= len) {
- len -= len_;
- } else {
- st.splice(i, 1, cur.slice(0, len), st[i+1], cur.slice(len));
- len = 0;
- }
- i += 2;
- }
- if (!style) return;
- if (overlay.opaque) {
- st.splice(start, i - start, txt, style);
- i = start + 2;
- } else {
- for (; start < i; start += 2) {
- var cur = st[start+1];
- st[start+1] = cur ? cur + " " + style : style;
- }
- }
- });
- }
-
- return st;
- }
-
- function getLineStyles(cm, line) {
- if (!line.styles || line.styles[0] != cm.state.modeGen)
- line.styles = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
- return line.styles;
- }
-
- // Lightweight form of highlight -- proceed over this line and
- // update state, but don't save a style array.
- function processLine(cm, line, state) {
- var mode = cm.doc.mode;
- var stream = new StringStream(line.text, cm.options.tabSize);
- if (line.text == "" && mode.blankLine) mode.blankLine(state);
- while (!stream.eol() && stream.pos <= 5000) {
- mode.token(stream, state);
- stream.start = stream.pos;
- }
- }
-
- var styleToClassCache = {};
- function styleToClass(style) {
- if (!style) return null;
- return styleToClassCache[style] ||
- (styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
- }
-
- function lineContent(cm, realLine, measure) {
- var merged, line = realLine, lineBefore, sawBefore, simple = true;
- while (merged = collapsedSpanAtStart(line)) {
- simple = false;
- line = getLine(cm.doc, merged.find().from.line);
- if (!lineBefore) lineBefore = line;
- }
-
- var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
- measure: null, addedOne: false, cm: cm};
- if (line.textClass) builder.pre.className = line.textClass;
-
- do {
- builder.measure = line == realLine && measure;
- builder.pos = 0;
- builder.addToken = builder.measure ? buildTokenMeasure : buildToken;
- if ((ie || webkit) && cm.getOption("lineWrapping"))
- builder.addToken = buildTokenSplitSpaces(builder.addToken);
- if (measure && sawBefore && line != realLine && !builder.addedOne) {
- measure[0] = builder.pre.appendChild(zeroWidthElement(cm.display.measure));
- builder.addedOne = true;
- }
- var next = insertLineContent(line, builder, getLineStyles(cm, line));
- sawBefore = line == lineBefore;
- if (next) {
- line = getLine(cm.doc, next.to.line);
- simple = false;
- }
- } while (next);
-
- if (measure && !builder.addedOne)
- measure[0] = builder.pre.appendChild(simple ? elt("span", "\u00a0") : zeroWidthElement(cm.display.measure));
- if (!builder.pre.firstChild && !lineIsHidden(cm.doc, realLine))
- builder.pre.appendChild(document.createTextNode("\u00a0"));
-
- var order;
- // Work around problem with the reported dimensions of single-char
- // direction spans on IE (issue #1129). See also the comment in
- // cursorCoords.
- if (measure && ie && (order = getOrder(line))) {
- var l = order.length - 1;
- if (order[l].from == order[l].to) --l;
- var last = order[l], prev = order[l - 1];
- if (last.from + 1 == last.to && prev && last.level < prev.level) {
- var span = measure[builder.pos - 1];
- if (span) span.parentNode.insertBefore(span.measureRight = zeroWidthElement(cm.display.measure),
- span.nextSibling);
- }
- }
-
- signal(cm, "renderLine", cm, realLine, builder.pre);
- return builder.pre;
- }
-
- var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
- function buildToken(builder, text, style, startStyle, endStyle) {
- if (!text) return;
- if (!tokenSpecialChars.test(text)) {
- builder.col += text.length;
- var content = document.createTextNode(text);
- } else {
- var content = document.createDocumentFragment(), pos = 0;
- while (true) {
- tokenSpecialChars.lastIndex = pos;
- var m = tokenSpecialChars.exec(text);
- var skipped = m ? m.index - pos : text.length - pos;
- if (skipped) {
- content.appendChild(document.createTextNode(text.slice(pos, pos + skipped)));
- builder.col += skipped;
- }
- if (!m) break;
- pos += skipped + 1;
- if (m[0] == "\t") {
- var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
- content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
- builder.col += tabWidth;
- } else {
- var token = elt("span", "\u2022", "cm-invalidchar");
- token.title = "\\u" + m[0].charCodeAt(0).toString(16);
- content.appendChild(token);
- builder.col += 1;
- }
- }
- }
- if (style || startStyle || endStyle || builder.measure) {
- var fullStyle = style || "";
- if (startStyle) fullStyle += startStyle;
- if (endStyle) fullStyle += endStyle;
- return builder.pre.appendChild(elt("span", [content], fullStyle));
- }
- builder.pre.appendChild(content);
- }
-
- function buildTokenMeasure(builder, text, style, startStyle, endStyle) {
- var wrapping = builder.cm.options.lineWrapping;
- for (var i = 0; i < text.length; ++i) {
- var ch = text.charAt(i), start = i == 0;
- if (ch >= "\ud800" && ch < "\udbff" && i < text.length - 1) {
- ch = text.slice(i, i + 2);
- ++i;
- } else if (i && wrapping &&
- spanAffectsWrapping.test(text.slice(i - 1, i + 1))) {
- builder.pre.appendChild(elt("wbr"));
- }
- var span = builder.measure[builder.pos] =
- buildToken(builder, ch, style,
- start && startStyle, i == text.length - 1 && endStyle);
- // In IE single-space nodes wrap differently than spaces
- // embedded in larger text nodes, except when set to
- // white-space: normal (issue #1268).
- if (ie && wrapping && ch == " " && i && !/\s/.test(text.charAt(i - 1)) &&
- i < text.length - 1 && !/\s/.test(text.charAt(i + 1)))
- span.style.whiteSpace = "normal";
- builder.pos += ch.length;
- }
- if (text.length) builder.addedOne = true;
- }
-
- function buildTokenSplitSpaces(inner) {
- function split(old) {
- var out = " ";
- for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
- out += " ";
- return out;
- }
- return function(builder, text, style, startStyle, endStyle) {
- return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle);
- };
- }
-
- function buildCollapsedSpan(builder, size, widget) {
- if (widget) {
- if (!builder.display) widget = widget.cloneNode(true);
- builder.pre.appendChild(widget);
- if (builder.measure && size) {
- builder.measure[builder.pos] = widget;
- builder.addedOne = true;
- }
- }
- builder.pos += size;
- }
-
- // Outputs a number of spans to make up a line, taking highlighting
- // and marked text into account.
- function insertLineContent(line, builder, styles) {
- var spans = line.markedSpans;
- if (!spans) {
- for (var i = 1; i < styles.length; i+=2)
- builder.addToken(builder, styles[i], styleToClass(styles[i+1]));
- return;
- }
-
- var allText = line.text, len = allText.length;
- var pos = 0, i = 1, text = "", style;
- var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed;
- for (;;) {
- if (nextChange == pos) { // Update current marker set
- spanStyle = spanEndStyle = spanStartStyle = "";
- collapsed = null; nextChange = Infinity;
- var foundBookmark = null;
- for (var j = 0; j < spans.length; ++j) {
- var sp = spans[j], m = sp.marker;
- if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
- if (sp.to != null && nextChange > sp.to) { nextChange = sp.to; spanEndStyle = ""; }
- if (m.className) spanStyle += " " + m.className;
- if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
- if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
- if (m.collapsed && (!collapsed || collapsed.marker.width < m.width))
- collapsed = sp;
- } else if (sp.from > pos && nextChange > sp.from) {
- nextChange = sp.from;
- }
- if (m.type == "bookmark" && sp.from == pos && m.replacedWith)
- foundBookmark = m.replacedWith;
- }
- if (collapsed && (collapsed.from || 0) == pos) {
- buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
- collapsed.from != null && collapsed.marker.replacedWith);
- if (collapsed.to == null) return collapsed.marker.find();
- }
- if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
- }
- if (pos >= len) break;
-
- var upto = Math.min(len, nextChange);
- while (true) {
- if (text) {
- var end = pos + text.length;
- if (!collapsed) {
- var tokenText = end > upto ? text.slice(0, upto - pos) : text;
- builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
- spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "");
- }
- if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
- pos = end;
- spanStartStyle = "";
- }
- text = styles[i++]; style = styleToClass(styles[i++]);
- }
- }
- }
-
- // DOCUMENT DATA STRUCTURE
-
- function updateDoc(doc, change, markedSpans, selAfter, estimateHeight) {
- function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
- function update(line, text, spans) {
- updateLine(line, text, spans, estimateHeight);
- signalLater(line, "change", line, change);
- }
-
- var from = change.from, to = change.to, text = change.text;
- var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
- var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
-
- // First adjust the line structure
- if (from.ch == 0 && to.ch == 0 && lastText == "") {
- // This is a whole-line replace. Treated specially to make
- // sure line objects move the way they are supposed to.
- for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
- added.push(makeLine(text[i], spansFor(i), estimateHeight));
- update(lastLine, lastLine.text, lastSpans);
- if (nlines) doc.remove(from.line, nlines);
- if (added.length) doc.insert(from.line, added);
- } else if (firstLine == lastLine) {
- if (text.length == 1) {
- update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
- } else {
- for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
- added.push(makeLine(text[i], spansFor(i), estimateHeight));
- added.push(makeLine(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
- doc.insert(from.line + 1, added);
- }
- } else if (text.length == 1) {
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
- doc.remove(from.line + 1, nlines);
- } else {
- update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
- update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
- for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
- added.push(makeLine(text[i], spansFor(i), estimateHeight));
- if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
- doc.insert(from.line + 1, added);
- }
-
- signalLater(doc, "change", doc, change);
- setSelection(doc, selAfter.anchor, selAfter.head, null, true);
- }
-
- function LeafChunk(lines) {
- this.lines = lines;
- this.parent = null;
- for (var i = 0, e = lines.length, height = 0; i < e; ++i) {
- lines[i].parent = this;
- height += lines[i].height;
- }
- this.height = height;
- }
-
- LeafChunk.prototype = {
- chunkSize: function() { return this.lines.length; },
- removeInner: function(at, n) {
- for (var i = at, e = at + n; i < e; ++i) {
- var line = this.lines[i];
- this.height -= line.height;
- cleanUpLine(line);
- signalLater(line, "delete");
- }
- this.lines.splice(at, n);
- },
- collapse: function(lines) {
- lines.splice.apply(lines, [lines.length, 0].concat(this.lines));
- },
- insertInner: function(at, lines, height) {
- this.height += height;
- this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
- for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
- },
- iterN: function(at, n, op) {
- for (var e = at + n; at < e; ++at)
- if (op(this.lines[at])) return true;
- }
- };
-
- function BranchChunk(children) {
- this.children = children;
- var size = 0, height = 0;
- for (var i = 0, e = children.length; i < e; ++i) {
- var ch = children[i];
- size += ch.chunkSize(); height += ch.height;
- ch.parent = this;
- }
- this.size = size;
- this.height = height;
- this.parent = null;
- }
-
- BranchChunk.prototype = {
- chunkSize: function() { return this.size; },
- removeInner: function(at, n) {
- this.size -= n;
- for (var i = 0; i < this.children.length; ++i) {
- var child = this.children[i], sz = child.chunkSize();
- if (at < sz) {
- var rm = Math.min(n, sz - at), oldHeight = child.height;
- child.removeInner(at, rm);
- this.height -= oldHeight - child.height;
- if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
- if ((n -= rm) == 0) break;
- at = 0;
- } else at -= sz;
- }
- if (this.size - n < 25) {
- var lines = [];
- this.collapse(lines);
- this.children = [new LeafChunk(lines)];
- this.children[0].parent = this;
- }
- },
- collapse: function(lines) {
- for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);
- },
- insertInner: function(at, lines, height) {
- this.size += lines.length;
- this.height += height;
- for (var i = 0, e = this.children.length; i < e; ++i) {
- var child = this.children[i], sz = child.chunkSize();
- if (at <= sz) {
- child.insertInner(at, lines, height);
- if (child.lines && child.lines.length > 50) {
- while (child.lines.length > 50) {
- var spilled = child.lines.splice(child.lines.length - 25, 25);
- var newleaf = new LeafChunk(spilled);
- child.height -= newleaf.height;
- this.children.splice(i + 1, 0, newleaf);
- newleaf.parent = this;
- }
- this.maybeSpill();
- }
- break;
- }
- at -= sz;
- }
- },
- maybeSpill: function() {
- if (this.children.length <= 10) return;
- var me = this;
- do {
- var spilled = me.children.splice(me.children.length - 5, 5);
- var sibling = new BranchChunk(spilled);
- if (!me.parent) { // Become the parent node
- var copy = new BranchChunk(me.children);
- copy.parent = me;
- me.children = [copy, sibling];
- me = copy;
- } else {
- me.size -= sibling.size;
- me.height -= sibling.height;
- var myIndex = indexOf(me.parent.children, me);
- me.parent.children.splice(myIndex + 1, 0, sibling);
- }
- sibling.parent = me.parent;
- } while (me.children.length > 10);
- me.parent.maybeSpill();
- },
- iterN: function(at, n, op) {
- for (var i = 0, e = this.children.length; i < e; ++i) {
- var child = this.children[i], sz = child.chunkSize();
- if (at < sz) {
- var used = Math.min(n, sz - at);
- if (child.iterN(at, used, op)) return true;
- if ((n -= used) == 0) break;
- at = 0;
- } else at -= sz;
- }
- }
- };
-
- var nextDocId = 0;
- var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
- if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
- if (firstLine == null) firstLine = 0;
-
- BranchChunk.call(this, [new LeafChunk([makeLine("", null)])]);
- this.first = firstLine;
- this.scrollTop = this.scrollLeft = 0;
- this.cantEdit = false;
- this.history = makeHistory();
- this.frontier = firstLine;
- var start = Pos(firstLine, 0);
- this.sel = {from: start, to: start, head: start, anchor: start, shift: false, extend: false, goalColumn: null};
- this.id = ++nextDocId;
- this.modeOption = mode;
-
- if (typeof text == "string") text = splitLines(text);
- updateDoc(this, {from: start, to: start, text: text}, null, {head: start, anchor: start});
- };
-
- Doc.prototype = createObj(BranchChunk.prototype, {
- iter: function(from, to, op) {
- if (op) this.iterN(from - this.first, to - from, op);
- else this.iterN(this.first, this.first + this.size, from);
- },
-
- insert: function(at, lines) {
- var height = 0;
- for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;
- this.insertInner(at - this.first, lines, height);
- },
- remove: function(at, n) { this.removeInner(at - this.first, n); },
-
- getValue: function(lineSep) {
- var lines = getLines(this, this.first, this.first + this.size);
- if (lineSep === false) return lines;
- return lines.join(lineSep || "\n");
- },
- setValue: function(code) {
- var top = Pos(this.first, 0), last = this.first + this.size - 1;
- makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
- text: splitLines(code), origin: "setValue"},
- {head: top, anchor: top}, true);
- },
- replaceRange: function(code, from, to, origin) {
- from = clipPos(this, from);
- to = to ? clipPos(this, to) : from;
- replaceRange(this, code, from, to, origin);
- },
- getRange: function(from, to, lineSep) {
- var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
- if (lineSep === false) return lines;
- return lines.join(lineSep || "\n");
- },
-
- getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
- setLine: function(line, text) {
- if (isLine(this, line))
- replaceRange(this, text, Pos(line, 0), clipPos(this, Pos(line)));
- },
- removeLine: function(line) {
- if (isLine(this, line))
- replaceRange(this, "", Pos(line, 0), clipPos(this, Pos(line + 1, 0)));
- },
-
- getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
- getLineNumber: function(line) {return lineNo(line);},
-
- lineCount: function() {return this.size;},
- firstLine: function() {return this.first;},
- lastLine: function() {return this.first + this.size - 1;},
-
- clipPos: function(pos) {return clipPos(this, pos);},
-
- getCursor: function(start) {
- var sel = this.sel, pos;
- if (start == null || start == "head") pos = sel.head;
- else if (start == "anchor") pos = sel.anchor;
- else if (start == "end" || start === false) pos = sel.to;
- else pos = sel.from;
- return copyPos(pos);
- },
- somethingSelected: function() {return !posEq(this.sel.head, this.sel.anchor);},
-
- setCursor: docOperation(function(line, ch, extend) {
- var pos = clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line);
- if (extend) extendSelection(this, pos);
- else setSelection(this, pos, pos);
- }),
- setSelection: docOperation(function(anchor, head) {
- setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
- }),
- extendSelection: docOperation(function(from, to) {
- extendSelection(this, clipPos(this, from), to && clipPos(this, to));
- }),
-
- getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
- replaceSelection: function(code, collapse, origin) {
- makeChange(this, {from: this.sel.from, to: this.sel.to, text: splitLines(code), origin: origin}, collapse || "around");
- },
- undo: docOperation(function() {makeChangeFromHistory(this, "undo");}),
- redo: docOperation(function() {makeChangeFromHistory(this, "redo");}),
-
- setExtending: function(val) {this.sel.extend = val;},
-
- historySize: function() {
- var hist = this.history;
- return {undo: hist.done.length, redo: hist.undone.length};
- },
- clearHistory: function() {this.history = makeHistory();},
-
- markClean: function() {
- this.history.dirtyCounter = 0;
- this.history.lastOp = this.history.lastOrigin = null;
- },
- isClean: function () {return this.history.dirtyCounter == 0;},
-
- getHistory: function() {
- return {done: copyHistoryArray(this.history.done),
- undone: copyHistoryArray(this.history.undone)};
- },
- setHistory: function(histData) {
- var hist = this.history = makeHistory();
- hist.done = histData.done.slice(0);
- hist.undone = histData.undone.slice(0);
- },
-
- markText: function(from, to, options) {
- return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
- },
- setBookmark: function(pos, options) {
- var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
- insertLeft: options && options.insertLeft};
- pos = clipPos(this, pos);
- return markText(this, pos, pos, realOpts, "bookmark");
- },
- findMarksAt: function(pos) {
- pos = clipPos(this, pos);
- var markers = [], spans = getLine(this, pos.line).markedSpans;
- if (spans) for (var i = 0; i < spans.length; ++i) {
- var span = spans[i];
- if ((span.from == null || span.from <= pos.ch) &&
- (span.to == null || span.to >= pos.ch))
- markers.push(span.marker.parent || span.marker);
- }
- return markers;
- },
- getAllMarks: function() {
- var markers = [];
- this.iter(function(line) {
- var sps = line.markedSpans;
- if (sps) for (var i = 0; i < sps.length; ++i)
- if (sps[i].from != null) markers.push(sps[i].marker);
- });
- return markers;
- },
-
- posFromIndex: function(off) {
- var ch, lineNo = this.first;
- this.iter(function(line) {
- var sz = line.text.length + 1;
- if (sz > off) { ch = off; return true; }
- off -= sz;
- ++lineNo;
- });
- return clipPos(this, Pos(lineNo, ch));
- },
- indexFromPos: function (coords) {
- coords = clipPos(this, coords);
- var index = coords.ch;
- if (coords.line < this.first || coords.ch < 0) return 0;
- this.iter(this.first, coords.line, function (line) {
- index += line.text.length + 1;
- });
- return index;
- },
-
- copy: function(copyHistory) {
- var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
- doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
- doc.sel = {from: this.sel.from, to: this.sel.to, head: this.sel.head, anchor: this.sel.anchor,
- shift: this.sel.shift, extend: false, goalColumn: this.sel.goalColumn};
- if (copyHistory) {
- doc.history.undoDepth = this.history.undoDepth;
- doc.setHistory(this.getHistory());
- }
- return doc;
- },
-
- linkedDoc: function(options) {
- if (!options) options = {};
- var from = this.first, to = this.first + this.size;
- if (options.from != null && options.from > from) from = options.from;
- if (options.to != null && options.to < to) to = options.to;
- var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
- if (options.sharedHist) copy.history = this.history;
- (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
- copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
- return copy;
- },
- unlinkDoc: function(other) {
- if (other instanceof CodeMirror) other = other.doc;
- if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
- var link = this.linked[i];
- if (link.doc != other) continue;
- this.linked.splice(i, 1);
- other.unlinkDoc(this);
- break;
- }
- // If the histories were shared, split them again
- if (other.history == this.history) {
- var splitIds = [other.id];
- linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
- other.history = makeHistory();
- other.history.done = copyHistoryArray(this.history.done, splitIds);
- other.history.undone = copyHistoryArray(this.history.undone, splitIds);
- }
- },
- iterLinkedDocs: function(f) {linkedDocs(this, f);},
-
- getMode: function() {return this.mode;},
- getEditor: function() {return this.cm;}
- });
-
- Doc.prototype.eachLine = Doc.prototype.iter;
-
- // The Doc methods that should be available on CodeMirror instances
- var dontDelegate = "iter insert remove copy getEditor".split(" ");
- for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
- CodeMirror.prototype[prop] = (function(method) {
- return function() {return method.apply(this.doc, arguments);};
- })(Doc.prototype[prop]);
-
- function linkedDocs(doc, f, sharedHistOnly) {
- function propagate(doc, skip, sharedHist) {
- if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
- var rel = doc.linked[i];
- if (rel.doc == skip) continue;
- var shared = sharedHist && rel.sharedHist;
- if (sharedHistOnly && !shared) continue;
- f(rel.doc, shared);
- propagate(rel.doc, doc, shared);
- }
- }
- propagate(doc, null, true);
- }
-
- function attachDoc(cm, doc) {
- if (doc.cm) throw new Error("This document is already in use.");
- cm.doc = doc;
- doc.cm = cm;
- estimateLineHeights(cm);
- loadMode(cm);
- if (!cm.options.lineWrapping) computeMaxLength(cm);
- cm.options.mode = doc.modeOption;
- regChange(cm);
- }
-
- // LINE UTILITIES
-
- function getLine(chunk, n) {
- n -= chunk.first;
- while (!chunk.lines) {
- for (var i = 0;; ++i) {
- var child = chunk.children[i], sz = child.chunkSize();
- if (n < sz) { chunk = child; break; }
- n -= sz;
- }
- }
- return chunk.lines[n];
- }
-
- function getBetween(doc, start, end) {
- var out = [], n = start.line;
- doc.iter(start.line, end.line + 1, function(line) {
- var text = line.text;
- if (n == end.line) text = text.slice(0, end.ch);
- if (n == start.line) text = text.slice(start.ch);
- out.push(text);
- ++n;
- });
- return out;
- }
- function getLines(doc, from, to) {
- var out = [];
- doc.iter(from, to, function(line) { out.push(line.text); });
- return out;
- }
-
- function updateLineHeight(line, height) {
- var diff = height - line.height;
- for (var n = line; n; n = n.parent) n.height += diff;
- }
-
- function lineNo(line) {
- if (line.parent == null) return null;
- var cur = line.parent, no = indexOf(cur.lines, line);
- for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
- for (var i = 0;; ++i) {
- if (chunk.children[i] == cur) break;
- no += chunk.children[i].chunkSize();
- }
- }
- return no + cur.first;
- }
-
- function lineAtHeight(chunk, h) {
- var n = chunk.first;
- outer: do {
- for (var i = 0, e = chunk.children.length; i < e; ++i) {
- var child = chunk.children[i], ch = child.height;
- if (h < ch) { chunk = child; continue outer; }
- h -= ch;
- n += child.chunkSize();
- }
- return n;
- } while (!chunk.lines);
- for (var i = 0, e = chunk.lines.length; i < e; ++i) {
- var line = chunk.lines[i], lh = line.height;
- if (h < lh) break;
- h -= lh;
- }
- return n + i;
- }
-
- function heightAtLine(cm, lineObj) {
- lineObj = visualLine(cm.doc, lineObj);
-
- var h = 0, chunk = lineObj.parent;
- for (var i = 0; i < chunk.lines.length; ++i) {
- var line = chunk.lines[i];
- if (line == lineObj) break;
- else h += line.height;
- }
- for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
- for (var i = 0; i < p.children.length; ++i) {
- var cur = p.children[i];
- if (cur == chunk) break;
- else h += cur.height;
- }
- }
- return h;
- }
-
- function getOrder(line) {
- var order = line.order;
- if (order == null) order = line.order = bidiOrdering(line.text);
- return order;
- }
-
- // HISTORY
-
- function makeHistory() {
- return {
- // Arrays of history events. Doing something adds an event to
- // done and clears undo. Undoing moves events from done to
- // undone, redoing moves them in the other direction.
- done: [], undone: [], undoDepth: Infinity,
- // Used to track when changes can be merged into a single undo
- // event
- lastTime: 0, lastOp: null, lastOrigin: null,
- // Used by the isClean() method
- dirtyCounter: 0
- };
- }
-
- function attachLocalSpans(doc, change, from, to) {
- var existing = change["spans_" + doc.id], n = 0;
- doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
- if (line.markedSpans)
- (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
- ++n;
- });
- }
-
- function historyChangeFromChange(doc, change) {
- var histChange = {from: change.from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
- attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
- linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
- return histChange;
- }
-
- function addToHistory(doc, change, selAfter, opId) {
- var hist = doc.history;
- hist.undone.length = 0;
- var time = +new Date, cur = lst(hist.done);
-
- if (cur &&
- (hist.lastOp == opId ||
- hist.lastOrigin == change.origin && change.origin &&
- ((change.origin.charAt(0) == "+" && hist.lastTime > time - 600) || change.origin.charAt(0) == "*"))) {
- // Merge this change into the last event
- var last = lst(cur.changes);
- if (posEq(change.from, change.to) && posEq(change.from, last.to)) {
- // Optimized case for simple insertion -- don't want to add
- // new changesets for every character typed
- last.to = changeEnd(change);
- } else {
- // Add new sub-event
- cur.changes.push(historyChangeFromChange(doc, change));
- }
- cur.anchorAfter = selAfter.anchor; cur.headAfter = selAfter.head;
- } else {
- // Can not be merged, start a new event.
- cur = {changes: [historyChangeFromChange(doc, change)],
- anchorBefore: doc.sel.anchor, headBefore: doc.sel.head,
- anchorAfter: selAfter.anchor, headAfter: selAfter.head};
- hist.done.push(cur);
- while (hist.done.length > hist.undoDepth)
- hist.done.shift();
- if (hist.dirtyCounter < 0)
- // The user has made a change after undoing past the last clean state.
- // We can never get back to a clean state now until markClean() is called.
- hist.dirtyCounter = NaN;
- else
- hist.dirtyCounter++;
- }
- hist.lastTime = time;
- hist.lastOp = opId;
- hist.lastOrigin = change.origin;
- }
-
- function removeClearedSpans(spans) {
- if (!spans) return null;
- for (var i = 0, out; i < spans.length; ++i) {
- if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
- else if (out) out.push(spans[i]);
- }
- return !out ? spans : out.length ? out : null;
- }
-
- function getOldSpans(doc, change) {
- var found = change["spans_" + doc.id];
- if (!found) return null;
- for (var i = 0, nw = []; i < change.text.length; ++i)
- nw.push(removeClearedSpans(found[i]));
- return nw;
- }
-
- // Used both to provide a JSON-safe object in .getHistory, and, when
- // detaching a document, to split the history in two
- function copyHistoryArray(events, newGroup) {
- for (var i = 0, copy = []; i < events.length; ++i) {
- var event = events[i], changes = event.changes, newChanges = [];
- copy.push({changes: newChanges, anchorBefore: event.anchorBefore, headBefore: event.headBefore,
- anchorAfter: event.anchorAfter, headAfter: event.headAfter});
- for (var j = 0; j < changes.length; ++j) {
- var change = changes[j], m;
- newChanges.push({from: change.from, to: change.to, text: change.text});
- if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
- if (indexOf(newGroup, Number(m[1])) > -1) {
- lst(newChanges)[prop] = change[prop];
- delete change[prop];
- }
- }
- }
- }
- return copy;
- }
-
- // Rebasing/resetting history to deal with externally-sourced changes
-
- function rebaseHistSel(pos, from, to, diff) {
- if (to < pos.line) {
- pos.line += diff;
- } else if (from < pos.line) {
- pos.line = from;
- pos.ch = 0;
- }
- }
-
- // Tries to rebase an array of history events given a change in the
- // document. If the change touches the same lines as the event, the
- // event, and everything 'behind' it, is discarded. If the change is
- // before the event, the event's positions are updated. Uses a
- // copy-on-write scheme for the positions, to avoid having to
- // reallocate them all on every rebase, but also avoid problems with
- // shared position objects being unsafely updated.
- function rebaseHistArray(array, from, to, diff) {
- for (var i = 0; i < array.length; ++i) {
- var sub = array[i], ok = true;
- for (var j = 0; j < sub.changes.length; ++j) {
- var cur = sub.changes[j];
- if (!sub.copied) { cur.from = copyPos(cur.from); cur.to = copyPos(cur.to); }
- if (to < cur.from.line) {
- cur.from.line += diff;
- cur.to.line += diff;
- } else if (from <= cur.to.line) {
- ok = false;
- break;
- }
- }
- if (!sub.copied) {
- sub.anchorBefore = copyPos(sub.anchorBefore); sub.headBefore = copyPos(sub.headBefore);
- sub.anchorAfter = copyPos(sub.anchorAfter); sub.readAfter = copyPos(sub.headAfter);
- sub.copied = true;
- }
- if (!ok) {
- array.splice(0, i + 1);
- i = 0;
- } else {
- rebaseHistSel(sub.anchorBefore); rebaseHistSel(sub.headBefore);
- rebaseHistSel(sub.anchorAfter); rebaseHistSel(sub.headAfter);
- }
- }
- }
-
- function rebaseHist(hist, change) {
- var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
- rebaseHistArray(hist.done, from, to, diff);
- rebaseHistArray(hist.undone, from, to, diff);
- }
-
- // EVENT OPERATORS
-
- function stopMethod() {e_stop(this);}
- // Ensure an event has a stop method.
- function addStop(event) {
- if (!event.stop) event.stop = stopMethod;
- return event;
- }
-
- function e_preventDefault(e) {
- if (e.preventDefault) e.preventDefault();
- else e.returnValue = false;
- }
- function e_stopPropagation(e) {
- if (e.stopPropagation) e.stopPropagation();
- else e.cancelBubble = true;
- }
- function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
- CodeMirror.e_stop = e_stop;
- CodeMirror.e_preventDefault = e_preventDefault;
- CodeMirror.e_stopPropagation = e_stopPropagation;
-
- function e_target(e) {return e.target || e.srcElement;}
- function e_button(e) {
- var b = e.which;
- if (b == null) {
- if (e.button & 1) b = 1;
- else if (e.button & 2) b = 3;
- else if (e.button & 4) b = 2;
- }
- if (mac && e.ctrlKey && b == 1) b = 3;
- return b;
- }
-
- // EVENT HANDLING
-
- function on(emitter, type, f) {
- if (emitter.addEventListener)
- emitter.addEventListener(type, f, false);
- else if (emitter.attachEvent)
- emitter.attachEvent("on" + type, f);
- else {
- var map = emitter._handlers || (emitter._handlers = {});
- var arr = map[type] || (map[type] = []);
- arr.push(f);
- }
- }
-
- function off(emitter, type, f) {
- if (emitter.removeEventListener)
- emitter.removeEventListener(type, f, false);
- else if (emitter.detachEvent)
- emitter.detachEvent("on" + type, f);
- else {
- var arr = emitter._handlers && emitter._handlers[type];
- if (!arr) return;
- for (var i = 0; i < arr.length; ++i)
- if (arr[i] == f) { arr.splice(i, 1); break; }
- }
- }
-
- function signal(emitter, type /*, values...*/) {
- var arr = emitter._handlers && emitter._handlers[type];
- if (!arr) return;
- var args = Array.prototype.slice.call(arguments, 2);
- for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
- }
-
- var delayedCallbacks, delayedCallbackDepth = 0;
- function signalLater(emitter, type /*, values...*/) {
- var arr = emitter._handlers && emitter._handlers[type];
- if (!arr) return;
- var args = Array.prototype.slice.call(arguments, 2);
- if (!delayedCallbacks) {
- ++delayedCallbackDepth;
- delayedCallbacks = [];
- setTimeout(fireDelayed, 0);
- }
- function bnd(f) {return function(){f.apply(null, args);};};
- for (var i = 0; i < arr.length; ++i)
- delayedCallbacks.push(bnd(arr[i]));
- }
-
- function fireDelayed() {
- --delayedCallbackDepth;
- var delayed = delayedCallbacks;
- delayedCallbacks = null;
- for (var i = 0; i < delayed.length; ++i) delayed[i]();
- }
-
- function hasHandler(emitter, type) {
- var arr = emitter._handlers && emitter._handlers[type];
- return arr && arr.length > 0;
- }
-
- CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
-
- // MISC UTILITIES
-
- // Number of pixels added to scroller and sizer to hide scrollbar
- var scrollerCutOff = 30;
-
- // Returned or thrown by various protocols to signal 'I'm not
- // handling this'.
- var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
-
- function Delayed() {this.id = null;}
- Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};
-
- // Counts the column offset in a string, taking tabs into account.
- // Used mostly to find indentation.
- function countColumn(string, end, tabSize, startIndex, startValue) {
- if (end == null) {
- end = string.search(/[^\s\u00a0]/);
- if (end == -1) end = string.length;
- }
- for (var i = startIndex || 0, n = startValue || 0; i < end; ++i) {
- if (string.charAt(i) == "\t") n += tabSize - (n % tabSize);
- else ++n;
- }
- return n;
- }
- CodeMirror.countColumn = countColumn;
-
- var spaceStrs = [""];
- function spaceStr(n) {
- while (spaceStrs.length <= n)
- spaceStrs.push(lst(spaceStrs) + " ");
- return spaceStrs[n];
- }
-
- function lst(arr) { return arr[arr.length-1]; }
-
- function selectInput(node) {
- if (ios) { // Mobile Safari apparently has a bug where select() is broken.
- node.selectionStart = 0;
- node.selectionEnd = node.value.length;
- } else node.select();
- }
-
- function indexOf(collection, elt) {
- if (collection.indexOf) return collection.indexOf(elt);
- for (var i = 0, e = collection.length; i < e; ++i)
- if (collection[i] == elt) return i;
- return -1;
- }
-
- function createObj(base, props) {
- function Obj() {}
- Obj.prototype = base;
- var inst = new Obj();
- if (props) copyObj(props, inst);
- return inst;
- }
-
- function copyObj(obj, target) {
- if (!target) target = {};
- for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
- return target;
- }
-
- function emptyArray(size) {
- for (var a = [], i = 0; i < size; ++i) a.push(undefined);
- return a;
- }
-
- function bind(f) {
- var args = Array.prototype.slice.call(arguments, 1);
- return function(){return f.apply(null, args);};
- }
-
- var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/;
- function isWordChar(ch) {
- return /\w/.test(ch) || ch > "\x80" &&
- (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
- }
-
- function isEmpty(obj) {
- for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
- return true;
- }
-
- var isExtendingChar = /[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;
-
- // DOM UTILITIES
-
- function elt(tag, content, className, style) {
- var e = document.createElement(tag);
- if (className) e.className = className;
- if (style) e.style.cssText = style;
- if (typeof content == "string") setTextContent(e, content);
- else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
- return e;
- }
-
- function removeChildren(e) {
- // IE will break all parent-child relations in subnodes when setting innerHTML
- if (!ie) e.innerHTML = "";
- else while (e.firstChild) e.removeChild(e.firstChild);
- return e;
- }
-
- function removeChildrenAndAdd(parent, e) {
- return removeChildren(parent).appendChild(e);
- }
-
- function setTextContent(e, str) {
- if (ie_lt9) {
- e.innerHTML = "";
- e.appendChild(document.createTextNode(str));
- } else e.textContent = str;
- }
-
- function getRect(node) {
- return node.getBoundingClientRect();
- }
- CodeMirror.replaceGetRect = function(f) { getRect = f; };
-
- // FEATURE DETECTION
-
- // Detect drag-and-drop
- var dragAndDrop = function() {
- // There is *some* kind of drag-and-drop support in IE6-8, but I
- // couldn't get it to work yet.
- if (ie_lt9) return false;
- var div = elt('div');
- return "draggable" in div || "dragDrop" in div;
- }();
-
- // For a reason I have yet to figure out, some browsers disallow
- // word wrapping between certain characters *only* if a new inline
- // element is started between them. This makes it hard to reliably
- // measure the position of things, since that requires inserting an
- // extra span. This terribly fragile set of regexps matches the
- // character combinations that suffer from this phenomenon on the
- // various browsers.
- var spanAffectsWrapping = /^$/; // Won't match any two-character string
- if (gecko) spanAffectsWrapping = /$'/;
- else if (safari && !/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent)) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
- else if (webkit) spanAffectsWrapping = /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.]|\?[\w~`@#$%\^&*(_=+{[|><]/;
-
- var knownScrollbarWidth;
- function scrollbarWidth(measure) {
- if (knownScrollbarWidth != null) return knownScrollbarWidth;
- var test = elt("div", null, null, "width: 50px; height: 50px; overflow-x: scroll");
- removeChildrenAndAdd(measure, test);
- if (test.offsetWidth)
- knownScrollbarWidth = test.offsetHeight - test.clientHeight;
- return knownScrollbarWidth || 0;
- }
-
- var zwspSupported;
- function zeroWidthElement(measure) {
- if (zwspSupported == null) {
- var test = elt("span", "\u200b");
- removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
- if (measure.firstChild.offsetHeight != 0)
- zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !ie_lt8;
- }
- if (zwspSupported) return elt("span", "\u200b");
- else return elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
- }
-
- // See if "".split is the broken IE version, if so, provide an
- // alternative way to split lines.
- var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
- var pos = 0, result = [], l = string.length;
- while (pos <= l) {
- var nl = string.indexOf("\n", pos);
- if (nl == -1) nl = string.length;
- var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
- var rt = line.indexOf("\r");
- if (rt != -1) {
- result.push(line.slice(0, rt));
- pos += rt + 1;
- } else {
- result.push(line);
- pos = nl + 1;
- }
- }
- return result;
- } : function(string){return string.split(/\r\n?|\n/);};
- CodeMirror.splitLines = splitLines;
-
- var hasSelection = window.getSelection ? function(te) {
- try { return te.selectionStart != te.selectionEnd; }
- catch(e) { return false; }
- } : function(te) {
- try {var range = te.ownerDocument.selection.createRange();}
- catch(e) {}
- if (!range || range.parentElement() != te) return false;
- return range.compareEndPoints("StartToEnd", range) != 0;
- };
-
- var hasCopyEvent = (function() {
- var e = elt("div");
- if ("oncopy" in e) return true;
- e.setAttribute("oncopy", "return;");
- return typeof e.oncopy == 'function';
- })();
-
- // KEY NAMING
-
- var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
- 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
- 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
- 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete",
- 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
- 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home",
- 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"};
- CodeMirror.keyNames = keyNames;
- (function() {
- // Number keys
- for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);
- // Alphabetic keys
- for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
- // Function keys
- for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
- })();
-
- // BIDI HELPERS
-
- function iterateBidiSections(order, from, to, f) {
- if (!order) return f(from, to, "ltr");
- for (var i = 0; i < order.length; ++i) {
- var part = order[i];
- if (part.from < to && part.to > from || from == to && part.to == from)
- f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
- }
- }
-
- function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
- function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
-
- function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
- function lineRight(line) {
- var order = getOrder(line);
- if (!order) return line.text.length;
- return bidiRight(lst(order));
- }
-
- function lineStart(cm, lineN) {
- var line = getLine(cm.doc, lineN);
- var visual = visualLine(cm.doc, line);
- if (visual != line) lineN = lineNo(visual);
- var order = getOrder(visual);
- var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
- return Pos(lineN, ch);
- }
- function lineEnd(cm, lineN) {
- var merged, line;
- while (merged = collapsedSpanAtEnd(line = getLine(cm.doc, lineN)))
- lineN = merged.find().to.line;
- var order = getOrder(line);
- var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
- return Pos(lineN, ch);
- }
-
- // This is somewhat involved. It is needed in order to move
- // 'visually' through bi-directional text -- i.e., pressing left
- // should make the cursor go left, even when in RTL text. The
- // tricky part is the 'jumps', where RTL and LTR text touch each
- // other. This often requires the cursor offset to move more than
- // one unit, in order to visually move one unit.
- function moveVisually(line, start, dir, byUnit) {
- var bidi = getOrder(line);
- if (!bidi) return moveLogically(line, start, dir, byUnit);
- var moveOneUnit = byUnit ? function(pos, dir) {
- do pos += dir;
- while (pos > 0 && isExtendingChar.test(line.text.charAt(pos)));
- return pos;
- } : function(pos, dir) { return pos + dir; };
- var linedir = bidi[0].level;
- for (var i = 0; i < bidi.length; ++i) {
- var part = bidi[i], sticky = part.level % 2 == linedir;
- if ((part.from < start && part.to > start) ||
- (sticky && (part.from == start || part.to == start))) break;
- }
- var target = moveOneUnit(start, part.level % 2 ? -dir : dir);
-
- while (target != null) {
- if (part.level % 2 == linedir) {
- if (target < part.from || target > part.to) {
- part = bidi[i += dir];
- target = part && (dir > 0 == part.level % 2 ? moveOneUnit(part.to, -1) : moveOneUnit(part.from, 1));
- } else break;
- } else {
- if (target == bidiLeft(part)) {
- part = bidi[--i];
- target = part && bidiRight(part);
- } else if (target == bidiRight(part)) {
- part = bidi[++i];
- target = part && bidiLeft(part);
- } else break;
- }
- }
-
- return target < 0 || target > line.text.length ? null : target;
- }
-
- function moveLogically(line, start, dir, byUnit) {
- var target = start + dir;
- if (byUnit) while (target > 0 && isExtendingChar.test(line.text.charAt(target))) target += dir;
- return target < 0 || target > line.text.length ? null : target;
- }
-
- // Bidirectional ordering algorithm
- // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
- // that this (partially) implements.
-
- // One-char codes used for character types:
- // L (L): Left-to-Right
- // R (R): Right-to-Left
- // r (AL): Right-to-Left Arabic
- // 1 (EN): European Number
- // + (ES): European Number Separator
- // % (ET): European Number Terminator
- // n (AN): Arabic Number
- // , (CS): Common Number Separator
- // m (NSM): Non-Spacing Mark
- // b (BN): Boundary Neutral
- // s (B): Paragraph Separator
- // t (S): Segment Separator
- // w (WS): Whitespace
- // N (ON): Other Neutrals
-
- // Returns null if characters are ordered as they appear
- // (left-to-right), or an array of sections ({from, to, level}
- // objects) in the order in which they occur visually.
- var bidiOrdering = (function() {
- // Character types for codepoints 0 to 0xff
- var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";
- // Character types for codepoints 0x600 to 0x6ff
- var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";
- function charType(code) {
- if (code <= 0xff) return lowTypes.charAt(code);
- else if (0x590 <= code && code <= 0x5f4) return "R";
- else if (0x600 <= code && code <= 0x6ff) return arabicTypes.charAt(code - 0x600);
- else if (0x700 <= code && code <= 0x8ac) return "r";
- else return "L";
- }
-
- var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
- var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
- // Browsers seem to always treat the boundaries of block elements as being L.
- var outerType = "L";
-
- return function(str) {
- if (!bidiRE.test(str)) return false;
- var len = str.length, types = [];
- for (var i = 0, type; i < len; ++i)
- types.push(type = charType(str.charCodeAt(i)));
-
- // W1. Examine each non-spacing mark (NSM) in the level run, and
- // change the type of the NSM to the type of the previous
- // character. If the NSM is at the start of the level run, it will
- // get the type of sor.
- for (var i = 0, prev = outerType; i < len; ++i) {
- var type = types[i];
- if (type == "m") types[i] = prev;
- else prev = type;
- }
-
- // W2. Search backwards from each instance of a European number
- // until the first strong type (R, L, AL, or sor) is found. If an
- // AL is found, change the type of the European number to Arabic
- // number.
- // W3. Change all ALs to R.
- for (var i = 0, cur = outerType; i < len; ++i) {
- var type = types[i];
- if (type == "1" && cur == "r") types[i] = "n";
- else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
- }
-
- // W4. A single European separator between two European numbers
- // changes to a European number. A single common separator between
- // two numbers of the same type changes to that type.
- for (var i = 1, prev = types[0]; i < len - 1; ++i) {
- var type = types[i];
- if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
- else if (type == "," && prev == types[i+1] &&
- (prev == "1" || prev == "n")) types[i] = prev;
- prev = type;
- }
-
- // W5. A sequence of European terminators adjacent to European
- // numbers changes to all European numbers.
- // W6. Otherwise, separators and terminators change to Other
- // Neutral.
- for (var i = 0; i < len; ++i) {
- var type = types[i];
- if (type == ",") types[i] = "N";
- else if (type == "%") {
- for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
- var replace = (i && types[i-1] == "!") || (end < len - 1 && types[end] == "1") ? "1" : "N";
- for (var j = i; j < end; ++j) types[j] = replace;
- i = end - 1;
- }
- }
-
- // W7. Search backwards from each instance of a European number
- // until the first strong type (R, L, or sor) is found. If an L is
- // found, then change the type of the European number to L.
- for (var i = 0, cur = outerType; i < len; ++i) {
- var type = types[i];
- if (cur == "L" && type == "1") types[i] = "L";
- else if (isStrong.test(type)) cur = type;
- }
-
- // N1. A sequence of neutrals takes the direction of the
- // surrounding strong text if the text on both sides has the same
- // direction. European and Arabic numbers act as if they were R in
- // terms of their influence on neutrals. Start-of-level-run (sor)
- // and end-of-level-run (eor) are used at level run boundaries.
- // N2. Any remaining neutrals take the embedding direction.
- for (var i = 0; i < len; ++i) {
- if (isNeutral.test(types[i])) {
- for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
- var before = (i ? types[i-1] : outerType) == "L";
- var after = (end < len - 1 ? types[end] : outerType) == "L";
- var replace = before || after ? "L" : "R";
- for (var j = i; j < end; ++j) types[j] = replace;
- i = end - 1;
- }
- }
-
- // Here we depart from the documented algorithm, in order to avoid
- // building up an actual levels array. Since there are only three
- // levels (0, 1, 2) in an implementation that doesn't take
- // explicit embedding into account, we can build up the order on
- // the fly, without following the level-based algorithm.
- var order = [], m;
- for (var i = 0; i < len;) {
- if (countsAsLeft.test(types[i])) {
- var start = i;
- for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
- order.push({from: start, to: i, level: 0});
- } else {
- var pos = i, at = order.length;
- for (++i; i < len && types[i] != "L"; ++i) {}
- for (var j = pos; j < i;) {
- if (countsAsNum.test(types[j])) {
- if (pos < j) order.splice(at, 0, {from: pos, to: j, level: 1});
- var nstart = j;
- for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
- order.splice(at, 0, {from: nstart, to: j, level: 2});
- pos = j;
- } else ++j;
- }
- if (pos < i) order.splice(at, 0, {from: pos, to: i, level: 1});
- }
- }
- if (order[0].level == 1 && (m = str.match(/^\s+/))) {
- order[0].from = m[0].length;
- order.unshift({from: 0, to: m[0].length, level: 0});
- }
- if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
- lst(order).to -= m[0].length;
- order.push({from: len - m[0].length, to: len, level: 0});
- }
- if (order[0].level != lst(order).level)
- order.push({from: len, to: len, level: order[0].level});
-
- return order;
- };
- })();
-
- // THE END
-
- CodeMirror.version = "3.1 +";
-
- return CodeMirror;
-})();
-;
-CodeMirror.defineMode("css", function(config) {
- var indentUnit = config.indentUnit, type;
-
- var atMediaTypes = keySet([
- "all", "aural", "braille", "handheld", "print", "projection", "screen",
- "tty", "tv", "embossed"
- ]);
-
- var atMediaFeatures = keySet([
- "width", "min-width", "max-width", "height", "min-height", "max-height",
- "device-width", "min-device-width", "max-device-width", "device-height",
- "min-device-height", "max-device-height", "aspect-ratio",
- "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
- "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
- "max-color", "color-index", "min-color-index", "max-color-index",
- "monochrome", "min-monochrome", "max-monochrome", "resolution",
- "min-resolution", "max-resolution", "scan", "grid"
- ]);
-
- var propertyKeywords = keySet([
- "align-content", "align-items", "align-self", "alignment-adjust",
- "alignment-baseline", "anchor-point", "animation", "animation-delay",
- "animation-direction", "animation-duration", "animation-iteration-count",
- "animation-name", "animation-play-state", "animation-timing-function",
- "appearance", "azimuth", "backface-visibility", "background",
- "background-attachment", "background-clip", "background-color",
- "background-image", "background-origin", "background-position",
- "background-repeat", "background-size", "baseline-shift", "binding",
- "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
- "bookmark-target", "border", "border-bottom", "border-bottom-color",
- "border-bottom-left-radius", "border-bottom-right-radius",
- "border-bottom-style", "border-bottom-width", "border-collapse",
- "border-color", "border-image", "border-image-outset",
- "border-image-repeat", "border-image-slice", "border-image-source",
- "border-image-width", "border-left", "border-left-color",
- "border-left-style", "border-left-width", "border-radius", "border-right",
- "border-right-color", "border-right-style", "border-right-width",
- "border-spacing", "border-style", "border-top", "border-top-color",
- "border-top-left-radius", "border-top-right-radius", "border-top-style",
- "border-top-width", "border-width", "bottom", "box-decoration-break",
- "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
- "caption-side", "clear", "clip", "color", "color-profile", "column-count",
- "column-fill", "column-gap", "column-rule", "column-rule-color",
- "column-rule-style", "column-rule-width", "column-span", "column-width",
- "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
- "cue-after", "cue-before", "cursor", "direction", "display",
- "dominant-baseline", "drop-initial-after-adjust",
- "drop-initial-after-align", "drop-initial-before-adjust",
- "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
- "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
- "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
- "float", "float-offset", "font", "font-feature-settings", "font-family",
- "font-kerning", "font-language-override", "font-size", "font-size-adjust",
- "font-stretch", "font-style", "font-synthesis", "font-variant",
- "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
- "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
- "font-weight", "grid-cell", "grid-column", "grid-column-align",
- "grid-column-sizing", "grid-column-span", "grid-columns", "grid-flow",
- "grid-row", "grid-row-align", "grid-row-sizing", "grid-row-span",
- "grid-rows", "grid-template", "hanging-punctuation", "height", "hyphens",
- "icon", "image-orientation", "image-rendering", "image-resolution",
- "inline-box-align", "justify-content", "left", "letter-spacing",
- "line-break", "line-height", "line-stacking", "line-stacking-ruby",
- "line-stacking-shift", "line-stacking-strategy", "list-style",
- "list-style-image", "list-style-position", "list-style-type", "margin",
- "margin-bottom", "margin-left", "margin-right", "margin-top",
- "marker-offset", "marks", "marquee-direction", "marquee-loop",
- "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
- "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
- "nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline",
- "outline-color", "outline-offset", "outline-style", "outline-width",
- "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
- "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
- "page", "page-break-after", "page-break-before", "page-break-inside",
- "page-policy", "pause", "pause-after", "pause-before", "perspective",
- "perspective-origin", "pitch", "pitch-range", "play-during", "position",
- "presentation-level", "punctuation-trim", "quotes", "rendering-intent",
- "resize", "rest", "rest-after", "rest-before", "richness", "right",
- "rotation", "rotation-point", "ruby-align", "ruby-overhang",
- "ruby-position", "ruby-span", "size", "speak", "speak-as", "speak-header",
- "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
- "tab-size", "table-layout", "target", "target-name", "target-new",
- "target-position", "text-align", "text-align-last", "text-decoration",
- "text-decoration-color", "text-decoration-line", "text-decoration-skip",
- "text-decoration-style", "text-emphasis", "text-emphasis-color",
- "text-emphasis-position", "text-emphasis-style", "text-height",
- "text-indent", "text-justify", "text-outline", "text-shadow",
- "text-space-collapse", "text-transform", "text-underline-position",
- "text-wrap", "top", "transform", "transform-origin", "transform-style",
- "transition", "transition-delay", "transition-duration",
- "transition-property", "transition-timing-function", "unicode-bidi",
- "vertical-align", "visibility", "voice-balance", "voice-duration",
- "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
- "voice-volume", "volume", "white-space", "widows", "width", "word-break",
- "word-spacing", "word-wrap", "z-index"
- ]);
-
- var colorKeywords = keySet([
- "black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia",
- "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua"
- ]);
-
- var valueKeywords = keySet([
- "above", "absolute", "activeborder", "activecaption", "afar",
- "after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
- "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
- "arabic-indic", "armenian", "asterisks", "auto", "avoid", "background",
- "backwards", "baseline", "below", "bidi-override", "binary", "bengali",
- "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
- "both", "bottom", "break-all", "break-word", "button", "button-bevel",
- "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
- "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
- "cell", "center", "checkbox", "circle", "cjk-earthly-branch",
- "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
- "col-resize", "collapse", "compact", "condensed", "contain", "content",
- "content-box", "context-menu", "continuous", "copy", "cover", "crop",
- "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
- "decimal-leading-zero", "default", "default-button", "destination-atop",
- "destination-in", "destination-out", "destination-over", "devanagari",
- "disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
- "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
- "element", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
- "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
- "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
- "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
- "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
- "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
- "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et",
- "ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed",
- "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes",
- "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
- "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
- "help", "hidden", "hide", "higher", "highlight", "highlighttext",
- "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
- "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
- "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
- "inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
- "italic", "justify", "kannada", "katakana", "katakana-iroha", "khmer",
- "landscape", "lao", "large", "larger", "left", "level", "lighter",
- "line-through", "linear", "lines", "list-item", "listbox", "listitem",
- "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
- "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
- "lower-roman", "lowercase", "ltr", "malayalam", "match",
- "media-controls-background", "media-current-time-display",
- "media-fullscreen-button", "media-mute-button", "media-play-button",
- "media-return-to-realtime-button", "media-rewind-button",
- "media-seek-back-button", "media-seek-forward-button", "media-slider",
- "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
- "media-volume-slider-container", "media-volume-sliderthumb", "medium",
- "menu", "menulist", "menulist-button", "menulist-text",
- "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
- "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
- "narrower", "navy", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
- "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
- "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
- "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
- "outside", "overlay", "overline", "padding", "padding-box", "painted",
- "paused", "persian", "plus-darker", "plus-lighter", "pointer", "portrait",
- "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
- "radio", "read-only", "read-write", "read-write-plaintext-only", "relative",
- "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
- "ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
- "s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
- "searchfield-cancel-button", "searchfield-decoration",
- "searchfield-results-button", "searchfield-results-decoration",
- "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
- "single", "skip-white-space", "slide", "slider-horizontal",
- "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
- "small", "small-caps", "small-caption", "smaller", "solid", "somali",
- "source-atop", "source-in", "source-out", "source-over", "space", "square",
- "square-button", "start", "static", "status-bar", "stretch", "stroke",
- "sub", "subpixel-antialiased", "super", "sw-resize", "table",
- "table-caption", "table-cell", "table-column", "table-column-group",
- "table-footer-group", "table-header-group", "table-row", "table-row-group",
- "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
- "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
- "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
- "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
- "transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
- "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
- "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
- "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
- "visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider",
- "window", "windowframe", "windowtext", "x-large", "x-small", "xor",
- "xx-large", "xx-small", "yellow"
- ]);
-
- function keySet(array) { var keys = {}; for (var i = 0; i < array.length; ++i) keys[array[i]] = true; return keys; }
- function ret(style, tp) {type = tp; return style;}
-
- function tokenBase(stream, state) {
- var ch = stream.next();
- if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("def", stream.current());}
- else if (ch == "/" && stream.eat("*")) {
- state.tokenize = tokenCComment;
- return tokenCComment(stream, state);
- }
- else if (ch == "<" && stream.eat("!")) {
- state.tokenize = tokenSGMLComment;
- return tokenSGMLComment(stream, state);
- }
- else if (ch == "=") ret(null, "compare");
- else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
- else if (ch == "\"" || ch == "'") {
- state.tokenize = tokenString(ch);
- return state.tokenize(stream, state);
- }
- else if (ch == "#") {
- stream.eatWhile(/[\w\\\-]/);
- return ret("atom", "hash");
- }
- else if (ch == "!") {
- stream.match(/^\s*\w*/);
- return ret("keyword", "important");
- }
- else if (/\d/.test(ch)) {
- stream.eatWhile(/[\w.%]/);
- return ret("number", "unit");
- }
- else if (ch === "-") {
- if (/\d/.test(stream.peek())) {
- stream.eatWhile(/[\w.%]/);
- return ret("number", "unit");
- } else if (stream.match(/^[^-]+-/)) {
- return ret("meta", "meta");
- }
- }
- else if (/[,+>*\/]/.test(ch)) {
- return ret(null, "select-op");
- }
- else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
- return ret("qualifier", "qualifier");
- }
- else if (ch == ":") {
- return ret("operator", ch);
- }
- else if (/[;{}\[\]\(\)]/.test(ch)) {
- return ret(null, ch);
- }
- else if (ch == "u" && stream.match("rl(")) {
- stream.backUp(1);
- state.tokenize = tokenParenthesized;
- return ret("property", "variable");
- }
- else {
- stream.eatWhile(/[\w\\\-]/);
- return ret("property", "variable");
- }
- }
-
- function tokenCComment(stream, state) {
- var maybeEnd = false, ch;
- while ((ch = stream.next()) != null) {
- if (maybeEnd && ch == "/") {
- state.tokenize = tokenBase;
- break;
- }
- maybeEnd = (ch == "*");
- }
- return ret("comment", "comment");
- }
-
- function tokenSGMLComment(stream, state) {
- var dashes = 0, ch;
- while ((ch = stream.next()) != null) {
- if (dashes >= 2 && ch == ">") {
- state.tokenize = tokenBase;
- break;
- }
- dashes = (ch == "-") ? dashes + 1 : 0;
- }
- return ret("comment", "comment");
- }
-
- function tokenString(quote, nonInclusive) {
- return function(stream, state) {
- var escaped = false, ch;
- while ((ch = stream.next()) != null) {
- if (ch == quote && !escaped)
- break;
- escaped = !escaped && ch == "\\";
- }
- if (!escaped) {
- if (nonInclusive) stream.backUp(1);
- state.tokenize = tokenBase;
- }
- return ret("string", "string");
- };
- }
-
- function tokenParenthesized(stream, state) {
- stream.next(); // Must be '('
- if (!stream.match(/\s*[\"\']/, false))
- state.tokenize = tokenString(")", true);
- else
- state.tokenize = tokenBase;
- return ret(null, "(");
- }
-
- return {
- startState: function(base) {
- return {tokenize: tokenBase,
- baseIndent: base || 0,
- stack: []};
- },
-
- token: function(stream, state) {
-
- // Use these terms when applicable (see http://www.xanthir.com/blog/b4E50)
- //
- // rule** or **ruleset:
- // A selector + braces combo, or an at-rule.
- //
- // declaration block:
- // A sequence of declarations.
- //
- // declaration:
- // A property + colon + value combo.
- //
- // property value:
- // The entire value of a property.
- //
- // component value:
- // A single piece of a property value. Like the 5px in
- // text-shadow: 0 0 5px blue;. Can also refer to things that are
- // multiple terms, like the 1-4 terms that make up the background-size
- // portion of the background shorthand.
- //
- // term:
- // The basic unit of author-facing CSS, like a single number (5),
- // dimension (5px), string ("foo"), or function. Officially defined
- // by the CSS 2.1 grammar (look for the 'term' production)
- //
- //
- // simple selector:
- // A single atomic selector, like a type selector, an attr selector, a
- // class selector, etc.
- //
- // compound selector:
- // One or more simple selectors without a combinator. div.example is
- // compound, div > .example is not.
- //
- // complex selector:
- // One or more compound selectors chained with combinators.
- //
- // combinator:
- // The parts of selectors that express relationships. There are four
- // currently - the space (descendant combinator), the greater-than
- // bracket (child combinator), the plus sign (next sibling combinator),
- // and the tilda (following sibling combinator).
- //
- // sequence of selectors:
- // One or more of the named type of selector chained with commas.
-
- if (state.tokenize == tokenBase && stream.eatSpace()) return null;
- var style = state.tokenize(stream, state);
-
- // Changing style returned based on context
- var context = state.stack[state.stack.length-1];
- if (style == "property") {
- if (context == "propertyValue"){
- if (valueKeywords[stream.current()]) {
- style = "string-2";
- } else if (colorKeywords[stream.current()]) {
- style = "keyword";
- } else {
- style = "variable-2";
- }
- } else if (context == "rule") {
- if (!propertyKeywords[stream.current()]) {
- style += " error";
- }
- } else if (!context || context == "@media{") {
- style = "tag";
- } else if (context == "@media") {
- if (atMediaTypes[stream.current()]) {
- style = "attribute"; // Known attribute
- } else if (/^(only|not)$/i.test(stream.current())) {
- style = "keyword";
- } else if (stream.current().toLowerCase() == "and") {
- style = "error"; // "and" is only allowed in @mediaType
- } else if (atMediaFeatures[stream.current()]) {
- style = "error"; // Known property, should be in @mediaType(
- } else {
- // Unknown, expecting keyword or attribute, assuming attribute
- style = "attribute error";
- }
- } else if (context == "@mediaType") {
- if (atMediaTypes[stream.current()]) {
- style = "attribute";
- } else if (stream.current().toLowerCase() == "and") {
- style = "operator";
- } else if (/^(only|not)$/i.test(stream.current())) {
- style = "error"; // Only allowed in @media
- } else if (atMediaFeatures[stream.current()]) {
- style = "error"; // Known property, should be in parentheses
- } else {
- // Unknown attribute or property, but expecting property (preceded
- // by "and"). Should be in parentheses
- style = "error";
- }
- } else if (context == "@mediaType(") {
- if (propertyKeywords[stream.current()]) {
- // do nothing, remains "property"
- } else if (atMediaTypes[stream.current()]) {
- style = "error"; // Known property, should be in parentheses
- } else if (stream.current().toLowerCase() == "and") {
- style = "operator";
- } else if (/^(only|not)$/i.test(stream.current())) {
- style = "error"; // Only allowed in @media
- } else {
- style += " error";
- }
- } else {
- style = "error";
- }
- } else if (style == "atom") {
- if(!context || context == "@media{") {
- style = "builtin";
- } else if (context == "propertyValue") {
- if (!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
- style += " error";
- }
- } else {
- style = "error";
- }
- } else if (context == "@media" && type == "{") {
- style = "error";
- }
-
- // Push/pop context stack
- if (type == "{") {
- if (context == "@media" || context == "@mediaType") {
- state.stack.pop();
- state.stack[state.stack.length-1] = "@media{";
- }
- else state.stack.push("rule");
- }
- else if (type == "}") {
- state.stack.pop();
- if (context == "propertyValue") state.stack.pop();
- }
- else if (type == "@media") state.stack.push("@media");
- else if (context == "@media" && /\b(keyword|attribute)\b/.test(style))
- state.stack.push("@mediaType");
- else if (context == "@mediaType" && stream.current() == ",") state.stack.pop();
- else if (context == "@mediaType" && type == "(") state.stack.push("@mediaType(");
- else if (context == "@mediaType(" && type == ")") state.stack.pop();
- else if (context == "rule" && type == ":") state.stack.push("propertyValue");
- else if (context == "propertyValue" && type == ";") state.stack.pop();
- return style;
- },
-
- indent: function(state, textAfter) {
- var n = state.stack.length;
- if (/^\}/.test(textAfter))
- n -= state.stack[state.stack.length-1] == "propertyValue" ? 2 : 1;
- return state.baseIndent + n * indentUnit;
- },
-
- electricChars: "}"
- };
-});
-
-CodeMirror.defineMIME("text/css", "css");
-;
-// 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) {
- function inList(list) {
- for (var v = list; v; v = v.next)
- if (v.name == varname) return true;
- return false;
- }
- var state = cx.state;
- if (state.context) {
- cx.marked = "def";
- if (inList(state.localVars)) return;
- state.localVars = {name: varname, next: state.localVars};
- } else {
- if (inList(state.globalVars)) return;
- state.globalVars = {name: varname, next: state.globalVars};
- }
- }
-
- // 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,
- globalVars: parserConfig.globalVars,
- 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 });
-;
-CodeMirror.defineMode("xml", function(config, parserConfig) {
- var indentUnit = config.indentUnit;
- var Kludges = parserConfig.htmlMode ? {
- autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
- 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
- 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
- 'track': true, 'wbr': true},
- implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
- 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
- 'th': true, 'tr': true},
- contextGrabbers: {
- 'dd': {'dd': true, 'dt': true},
- 'dt': {'dd': true, 'dt': true},
- 'li': {'li': true},
- 'option': {'option': true, 'optgroup': true},
- 'optgroup': {'optgroup': true},
- 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
- 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
- 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
- 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
- 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
- 'rp': {'rp': true, 'rt': true},
- 'rt': {'rp': true, 'rt': true},
- 'tbody': {'tbody': true, 'tfoot': true},
- 'td': {'td': true, 'th': true},
- 'tfoot': {'tbody': true},
- 'th': {'td': true, 'th': true},
- 'thead': {'tbody': true, 'tfoot': true},
- 'tr': {'tr': true}
- },
- doNotIndent: {"pre": true},
- allowUnquoted: true,
- allowMissing: true
- } : {
- autoSelfClosers: {},
- implicitlyClosed: {},
- contextGrabbers: {},
- doNotIndent: {},
- allowUnquoted: false,
- allowMissing: false
- };
- var alignCDATA = parserConfig.alignCDATA;
-
- // Return variables for tokenizers
- var tagName, type;
-
- function inText(stream, state) {
- function chain(parser) {
- state.tokenize = parser;
- return parser(stream, state);
- }
-
- var ch = stream.next();
- if (ch == "<") {
- if (stream.eat("!")) {
- if (stream.eat("[")) {
- if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
- else return null;
- }
- else if (stream.match("--")) return chain(inBlock("comment", "-->"));
- else if (stream.match("DOCTYPE", true, true)) {
- stream.eatWhile(/[\w\._\-]/);
- return chain(doctype(1));
- }
- else return null;
- }
- else if (stream.eat("?")) {
- stream.eatWhile(/[\w\._\-]/);
- state.tokenize = inBlock("meta", "?>");
- return "meta";
- }
- else {
- var isClose = stream.eat("/");
- tagName = "";
- var c;
- while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
- if (!tagName) return "error";
- type = isClose ? "closeTag" : "openTag";
- state.tokenize = inTag;
- return "tag";
- }
- }
- else if (ch == "&") {
- var ok;
- if (stream.eat("#")) {
- if (stream.eat("x")) {
- ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
- } else {
- ok = stream.eatWhile(/[\d]/) && stream.eat(";");
- }
- } else {
- ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
- }
- return ok ? "atom" : "error";
- }
- else {
- stream.eatWhile(/[^&<]/);
- return null;
- }
- }
-
- function inTag(stream, state) {
- var ch = stream.next();
- if (ch == ">" || (ch == "/" && stream.eat(">"))) {
- state.tokenize = inText;
- type = ch == ">" ? "endTag" : "selfcloseTag";
- return "tag";
- }
- else if (ch == "=") {
- type = "equals";
- return null;
- }
- else if (/[\'\"]/.test(ch)) {
- state.tokenize = inAttribute(ch);
- return state.tokenize(stream, state);
- }
- else {
- stream.eatWhile(/[^\s\u00a0=<>\"\']/);
- return "word";
- }
- }
-
- function inAttribute(quote) {
- return function(stream, state) {
- while (!stream.eol()) {
- if (stream.next() == quote) {
- state.tokenize = inTag;
- break;
- }
- }
- return "string";
- };
- }
-
- function inBlock(style, terminator) {
- return function(stream, state) {
- while (!stream.eol()) {
- if (stream.match(terminator)) {
- state.tokenize = inText;
- break;
- }
- stream.next();
- }
- return style;
- };
- }
- function doctype(depth) {
- return function(stream, state) {
- var ch;
- while ((ch = stream.next()) != null) {
- if (ch == "<") {
- state.tokenize = doctype(depth + 1);
- return state.tokenize(stream, state);
- } else if (ch == ">") {
- if (depth == 1) {
- state.tokenize = inText;
- break;
- } else {
- state.tokenize = doctype(depth - 1);
- return state.tokenize(stream, state);
- }
- }
- }
- return "meta";
- };
- }
-
- var curState, setStyle;
- function pass() {
- for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
- }
- function cont() {
- pass.apply(null, arguments);
- return true;
- }
-
- function pushContext(tagName, startOfLine) {
- var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);
- curState.context = {
- prev: curState.context,
- tagName: tagName,
- indent: curState.indented,
- startOfLine: startOfLine,
- noIndent: noIndent
- };
- }
- function popContext() {
- if (curState.context) curState.context = curState.context.prev;
- }
-
- function element(type) {
- if (type == "openTag") {
- curState.tagName = tagName;
- return cont(attributes, endtag(curState.startOfLine));
- } else if (type == "closeTag") {
- var err = false;
- if (curState.context) {
- if (curState.context.tagName != tagName) {
- if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
- popContext();
- }
- err = !curState.context || curState.context.tagName != tagName;
- }
- } else {
- err = true;
- }
- if (err) setStyle = "error";
- return cont(endclosetag(err));
- }
- return cont();
- }
- function endtag(startOfLine) {
- return function(type) {
- var tagName = curState.tagName;
- curState.tagName = null;
- if (type == "selfcloseTag" ||
- (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))) {
- maybePopContext(tagName.toLowerCase());
- return cont();
- }
- if (type == "endTag") {
- maybePopContext(tagName.toLowerCase());
- pushContext(tagName, startOfLine);
- return cont();
- }
- return cont();
- };
- }
- function endclosetag(err) {
- return function(type) {
- if (err) setStyle = "error";
- if (type == "endTag") { popContext(); return cont(); }
- setStyle = "error";
- return cont(arguments.callee);
- };
- }
- function maybePopContext(nextTagName) {
- var parentTagName;
- while (true) {
- if (!curState.context) {
- return;
- }
- parentTagName = curState.context.tagName.toLowerCase();
- if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
- !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
- return;
- }
- popContext();
- }
- }
-
- function attributes(type) {
- if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}
- if (type == "endTag" || type == "selfcloseTag") return pass();
- setStyle = "error";
- return cont(attributes);
- }
- function attribute(type) {
- if (type == "equals") return cont(attvalue, attributes);
- if (!Kludges.allowMissing) setStyle = "error";
- else if (type == "word") setStyle = "attribute";
- return (type == "endTag" || type == "selfcloseTag") ? pass() : cont();
- }
- function attvalue(type) {
- if (type == "string") return cont(attvaluemaybe);
- if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return cont();}
- setStyle = "error";
- return (type == "endTag" || type == "selfCloseTag") ? pass() : cont();
- }
- function attvaluemaybe(type) {
- if (type == "string") return cont(attvaluemaybe);
- else return pass();
- }
-
- return {
- startState: function() {
- return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};
- },
-
- token: function(stream, state) {
- if (stream.sol()) {
- state.startOfLine = true;
- state.indented = stream.indentation();
- }
- if (stream.eatSpace()) return null;
-
- setStyle = type = tagName = null;
- var style = state.tokenize(stream, state);
- state.type = type;
- if ((style || type) && style != "comment") {
- curState = state;
- while (true) {
- var comb = state.cc.pop() || element;
- if (comb(type || style)) break;
- }
- }
- state.startOfLine = false;
- return setStyle || style;
- },
-
- indent: function(state, textAfter, fullLine) {
- var context = state.context;
- if ((state.tokenize != inTag && state.tokenize != inText) ||
- context && context.noIndent)
- return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
- if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
- if (context && /^<\//.test(textAfter))
- context = context.prev;
- while (context && !context.startOfLine)
- context = context.prev;
- if (context) return context.indent + indentUnit;
- else return 0;
- },
-
- electricChars: "/",
-
- configuration: parserConfig.htmlMode ? "html" : "xml"
- };
-});
-
-CodeMirror.defineMIME("text/xml", "xml");
-CodeMirror.defineMIME("application/xml", "xml");
-if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
- CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
-;
-CodeMirror.defineMode("htmlmixed", function(config) {
- var htmlMode = CodeMirror.getMode(config, {name: "xml", htmlMode: true});
- var jsMode = CodeMirror.getMode(config, "javascript");
- var cssMode = CodeMirror.getMode(config, "css");
-
- function html(stream, state) {
- var style = htmlMode.token(stream, state.htmlState);
- if (/(?:^|\s)tag(?:\s|$)/.test(style) && stream.current() == ">" && state.htmlState.context) {
- if (/^script$/i.test(state.htmlState.context.tagName)) {
- state.token = javascript;
- state.localState = jsMode.startState(htmlMode.indent(state.htmlState, ""));
- }
- else if (/^style$/i.test(state.htmlState.context.tagName)) {
- state.token = css;
- state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
- }
- }
- return style;
- }
- function maybeBackup(stream, pat, style) {
- var cur = stream.current();
- var close = cur.search(pat), m;
- if (close > -1) stream.backUp(cur.length - close);
- else if (m = cur.match(/<\/?$/)) {
- stream.backUp(cur.length);
- if (!stream.match(pat, false)) stream.match(cur[0]);
- }
- return style;
- }
- function javascript(stream, state) {
- if (stream.match(/^<\/\s*script\s*>/i, false)) {
- state.token = html;
- state.localState = null;
- return html(stream, state);
- }
- return maybeBackup(stream, /<\/\s*script\s*>/,
- jsMode.token(stream, state.localState));
- }
- function css(stream, state) {
- if (stream.match(/^<\/\s*style\s*>/i, false)) {
- state.token = html;
- state.localState = null;
- return html(stream, state);
- }
- return maybeBackup(stream, /<\/\s*style\s*>/,
- cssMode.token(stream, state.localState));
- }
-
- return {
- startState: function() {
- var state = htmlMode.startState();
- return {token: html, localState: null, mode: "html", htmlState: state};
- },
-
- copyState: function(state) {
- if (state.localState)
- var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);
- return {token: state.token, localState: local, mode: state.mode,
- htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
- },
-
- token: function(stream, state) {
- return state.token(stream, state);
- },
-
- indent: function(state, textAfter) {
- if (state.token == html || /^\s*<\//.test(textAfter))
- return htmlMode.indent(state.htmlState, textAfter);
- else if (state.token == javascript)
- return jsMode.indent(state.localState, textAfter);
- else
- return cssMode.indent(state.localState, textAfter);
- },
-
- electricChars: "/{}:",
-
- innerMode: function(state) {
- var mode = state.token == html ? htmlMode : state.token == javascript ? jsMode : cssMode;
- return {state: state.localState || state.htmlState, mode: mode};
- }
- };
-}, "xml", "javascript", "css");
-
-CodeMirror.defineMIME("text/html", "htmlmixed");
-;
-(function() {
- var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
- (document.documentMode == null || document.documentMode < 8);
-
- var Pos = CodeMirror.Pos;
- // Disable brace matching in long lines, since it'll cause hugely slow updates
- var maxLineLen = 1000;
-
- var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
- function findMatchingBracket(cm) {
- var cur = cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
- var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
- if (!match) return null;
- var forward = match.charAt(1) == ">", d = forward ? 1 : -1;
- var style = cm.getTokenAt(Pos(cur.line, pos + 1)).type;
-
- var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
- function scan(line, lineNo, start) {
- if (!line.text) return;
- var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1;
- if (start != null) pos = start + d;
- for (; pos != end; pos += d) {
- var ch = line.text.charAt(pos);
- if (re.test(ch) && cm.getTokenAt(Pos(lineNo, pos + 1)).type == style) {
- var match = matching[ch];
- if (match.charAt(1) == ">" == forward) stack.push(ch);
- else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
- else if (!stack.length) return {pos: pos, match: true};
- }
- }
- }
- for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) {
- if (i == cur.line) found = scan(line, i, pos);
- else found = scan(cm.getLineHandle(i), i);
- if (found) break;
- }
- return {from: Pos(cur.line, pos), to: found && Pos(i, found.pos), match: found && found.match};
- }
-
- function matchBrackets(cm, autoclear) {
- var found = findMatchingBracket(cm);
- if (!found || cm.getLine(found.from.line).length > maxLineLen ||
- found.to && cm.getLine(found.to.line).length > maxLineLen)
- return;
-
- var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
- var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style});
- var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style});
- // Kludge to work around the IE bug from issue #1193, where text
- // input stops going to the textare whever this fires.
- if (ie_lt8 && cm.state.focused) cm.display.input.focus();
- var clear = function() {
- cm.operation(function() { one.clear(); two && two.clear(); });
- };
- if (autoclear) setTimeout(clear, 800);
- else return clear;
- }
-
- var currentlyHighlighted = null;
- function doMatchBrackets(cm) {
- cm.operation(function() {
- if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
- if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false);
- });
- }
-
- CodeMirror.defineOption("matchBrackets", false, function(cm, val) {
- if (val) cm.on("cursorActivity", doMatchBrackets);
- else cm.off("cursorActivity", doMatchBrackets);
- });
-
- CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
- CodeMirror.defineExtension("findMatchingBracket", function(){return findMatchingBracket(this);});
-})();
-;
-(function() {
- var DEFAULT_BRACKETS = "()[]{}''\"\"";
- var SPACE_CHAR_REGEX = /\s/;
-
- CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
- var wasOn = old && old != CodeMirror.Init;
- if (val && !wasOn)
- cm.addKeyMap(buildKeymap(typeof val == "string" ? val : DEFAULT_BRACKETS));
- else if (!val && wasOn)
- cm.removeKeyMap("autoCloseBrackets");
- });
-
- function buildKeymap(pairs) {
- var map = {
- name : "autoCloseBrackets",
- Backspace: function(cm) {
- if (cm.somethingSelected()) return CodeMirror.Pass;
- var cur = cm.getCursor(), line = cm.getLine(cur.line);
- if (cur.ch && cur.ch < line.length &&
- pairs.indexOf(line.slice(cur.ch - 1, cur.ch + 1)) % 2 == 0)
- cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1));
- else
- return CodeMirror.Pass;
- }
- };
- var closingBrackets = [];
- for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
- if (left != right) closingBrackets.push(right);
- function surround(cm) {
- var selection = cm.getSelection();
- cm.replaceSelection(left + selection + right);
- }
- function maybeOverwrite(cm) {
- var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1));
- if (ahead != right || cm.somethingSelected()) return CodeMirror.Pass;
- else cm.execCommand("goCharRight");
- }
- map["'" + left + "'"] = function(cm) {
- if (cm.somethingSelected()) return surround(cm);
- if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return;
- var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1);
- var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch);
- if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || SPACE_CHAR_REGEX.test(nextChar))
- cm.replaceSelection(left + right, {head: ahead, anchor: ahead});
- else
- return CodeMirror.Pass;
- };
- if (left != right) map["'" + right + "'"] = maybeOverwrite;
- })(pairs.charAt(i), pairs.charAt(i + 1));
- return map;
- }
-})();
-;
-// Because sometimes you need to mark the selected *text*.
-//
-// Adds an option 'styleSelectedText' which, when enabled, gives
-// selected text the CSS class "CodeMirror-selectedtext".
-
-(function() {
- "use strict";
-
- CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
- var prev = old && old != CodeMirror.Init;
- if (val && !prev) {
- updateSelectedText(cm);
- cm.on("cursorActivity", updateSelectedText);
- } else if (!val && prev) {
- cm.off("cursorActivity", updateSelectedText);
- clearSelectedText(cm);
- delete cm._selectionMark;
- }
- });
-
- function clearSelectedText(cm) {
- if (cm._selectionMark) cm._selectionMark.clear();
- }
-
- function updateSelectedText(cm) {
- clearSelectedText(cm);
-
- if (cm.somethingSelected())
- cm._selectionMark = cm.markText(cm.getCursor("start"), cm.getCursor("end"),
- {className: "CodeMirror-selectedtext"});
- else
- cm._selectionMark = null;
- }
-})();
-;
-
-/**
- * @constructor
- * @extends {WebInspector.View}
- * @implements {WebInspector.TextEditor}
- * @param {?string} url
- * @param {WebInspector.TextEditorDelegate} delegate
- */
-WebInspector.CodeMirrorTextEditor = function(url, delegate)
-{
- WebInspector.View.call(this);
- this._delegate = delegate;
- this._url = url;
-
- this.registerRequiredCSS("cm/codemirror.css");
- this.registerRequiredCSS("cm/cmdevtools.css");
-
- this._codeMirror = window.CodeMirror(this.element, {
- lineNumbers: true,
- gutters: ["CodeMirror-linenumbers"],
- matchBrackets: true,
- smartIndent: false,
- styleSelectedText: true,
- electricChars: false,
- autoCloseBrackets: true
- });
-
- var extraKeys = {};
- var indent = WebInspector.settings.textEditorIndent.get();
- if (indent === WebInspector.TextUtils.Indent.TabCharacter) {
- this._codeMirror.setOption("indentWithTabs", true);
- this._codeMirror.setOption("indentUnit", 4);
- } else {
- this._codeMirror.setOption("indentWithTabs", false);
- this._codeMirror.setOption("indentUnit", indent.length);
- extraKeys.Tab = function(codeMirror)
- {
- if (codeMirror.somethingSelected())
- return CodeMirror.Pass;
- codeMirror.replaceRange(indent, codeMirror.getCursor());
- }
- }
- this._codeMirror.setOption("extraKeys", extraKeys);
-
- this._tokenHighlighter = new WebInspector.CodeMirrorTextEditor.TokenHighlighter(this._codeMirror);
- this._blockIndentController = new WebInspector.CodeMirrorTextEditor.BlockIndentController(this._codeMirror);
- this._fixWordMovement = new WebInspector.CodeMirrorTextEditor.FixWordMovement(this._codeMirror);
-
- this._codeMirror.on("change", this._change.bind(this));
- this._codeMirror.on("gutterClick", this._gutterClick.bind(this));
- this._codeMirror.on("cursorActivity", this._cursorActivity.bind(this));
- this._codeMirror.on("scroll", this._scroll.bind(this));
- this.element.addEventListener("contextmenu", this._contextMenu.bind(this));
-
- this._lastRange = this.range();
-
- this.element.firstChild.addStyleClass("source-code");
- this.element.firstChild.addStyleClass("fill");
- this._elementToWidget = new Map();
- this._nestedUpdatesCounter = 0;
-
- this.element.addEventListener("focus", this._handleElementFocus.bind(this), false);
- this.element.tabIndex = 0;
- this._setupSelectionColor();
-}
-
-WebInspector.CodeMirrorTextEditor.prototype = {
-
- undo: function()
- {
- this._codeMirror.undo();
- },
-
- redo: function()
- {
- this._codeMirror.redo();
- },
-
- _setupSelectionColor: function()
- {
- if (WebInspector.CodeMirrorTextEditor._selectionStyleInjected)
- return;
- WebInspector.CodeMirrorTextEditor._selectionStyleInjected = true;
- var backgroundColor = WebInspector.getSelectionBackgroundColor();
- var backgroundColorRule = backgroundColor ? ".CodeMirror .CodeMirror-selected { background-color: " + backgroundColor + ";}" : "";
- var foregroundColor = WebInspector.getSelectionForegroundColor();
- var foregroundColorRule = foregroundColor ? ".CodeMirror .CodeMirror-selectedtext { color: " + foregroundColor + "!important;}" : "";
- if (!foregroundColorRule && !backgroundColorRule)
- return;
-
- var style = document.createElement("style");
- style.textContent = backgroundColorRule + foregroundColorRule;
- document.head.appendChild(style);
- },
-
- /**
- * @param {number} lineNumber
- * @param {number} column
- * @return {?{x: number, y: number, height: number}}
- */
- cursorPositionToCoordinates: function(lineNumber, column)
- {
- if (lineNumber >= this._codeMirror.lineCount || column > this._codeMirror.getLine(lineNumber).length || lineNumber < 0 || column < 0)
- return null;
-
- var metrics = this._codeMirror.cursorCoords(new CodeMirror.Pos(lineNumber, column));
-
- return {
- x: metrics.left,
- y: metrics.top,
- height: metrics.bottom - metrics.top
- };
- },
-
- /**
- * @param {number} x
- * @param {number} y
- * @return {?WebInspector.TextRange}
- */
- coordinatesToCursorPosition: function(x, y)
- {
- var element = document.elementFromPoint(x, y);
- if (!element || !element.isSelfOrDescendant(this._codeMirror.getWrapperElement()))
- return null;
- var gutterBox = this._codeMirror.getGutterElement().boxInWindow();
- if (x >= gutterBox.x && x <= gutterBox.x + gutterBox.width &&
- y >= gutterBox.y && y <= gutterBox.y + gutterBox.height)
- return null;
- var coords = this._codeMirror.coordsChar({left: x, top: y});
- ++coords.ch;
- return this._toRange(coords, coords);
- },
-
- _convertTokenType: function(tokenType)
- {
- if (tokenType.startsWith("variable") || tokenType.startsWith("property") || tokenType === "def")
- return "javascript-ident";
- if (tokenType === "string-2")
- return "javascript-regexp";
- if (tokenType === "number" || tokenType === "comment" || tokenType === "string")
- return "javascript-" + tokenType;
- return null;
- },
-
- /**
- * @param {number} lineNumber
- * @param {number} column
- * @return {?{startColumn: number, endColumn: number, type: string}}
- */
- tokenAtTextPosition: function(lineNumber, column)
- {
- if (lineNumber < 0 || lineNumber >= this._codeMirror.lineCount())
- return null;
- var token = this._codeMirror.getTokenAt(new CodeMirror.Pos(lineNumber, column || 1));
- if (!token || !token.type)
- return null;
- var convertedType = this._convertTokenType(token.type);
- if (!convertedType)
- return null;
- return {
- startColumn: token.start,
- endColumn: token.end - 1,
- type: convertedType
- };
- },
-
- /**
- * @param {WebInspector.TextRange} textRange
- * @return {string}
- */
- copyRange: function(textRange)
- {
- var pos = this._toPos(textRange);
- return this._codeMirror.getRange(pos.start, pos.end);
- },
-
- /**
- * @return {boolean}
- */
- isClean: function()
- {
- return this._codeMirror.isClean();
- },
-
- markClean: function()
- {
- this._codeMirror.markClean();
- },
-
- /**
- * @param {string} mimeType
- */
- set mimeType(mimeType)
- {
- this._codeMirror.setOption("mode", mimeType);
- switch(mimeType) {
- case "text/html": this._codeMirror.setOption("theme", "web-inspector-html"); break;
- case "text/css": this._codeMirror.setOption("theme", "web-inspector-css"); break;
- case "text/javascript": this._codeMirror.setOption("theme", "web-inspector-js"); break;
- }
- },
-
- /**
- * @param {boolean} readOnly
- */
- setReadOnly: function(readOnly)
- {
- this._codeMirror.setOption("readOnly", readOnly ? "nocursor" : false);
- },
-
- /**
- * @return {boolean}
- */
- readOnly: function()
- {
- return !!this._codeMirror.getOption("readOnly");
- },
-
- /**
- * @param {Object} highlightDescriptor
- */
- removeHighlight: function(highlightDescriptor)
- {
- highlightDescriptor.clear();
- },
-
- /**
- * @param {WebInspector.TextRange} range
- * @param {string} cssClass
- * @return {Object}
- */
- highlightRange: function(range, cssClass)
- {
- var pos = this._toPos(range);
- ++pos.end.ch;
- return this._codeMirror.markText(pos.start, pos.end, {
- className: cssClass,
- startStyle: cssClass + "-start",
- endStyle: cssClass + "-end"
- });
- },
-
- /**
- * @param {string} regex
- * @param {string} cssClass
- * @return {Object}
- */
- highlightRegex: function(regex, cssClass) { },
-
- /**
- * @return {Element}
- */
- defaultFocusedElement: function()
- {
- return this.element;
- },
-
- focus: function()
- {
- this._codeMirror.focus();
- },
-
- _handleElementFocus: function()
- {
- this._codeMirror.focus();
- },
-
- beginUpdates: function()
- {
- ++this._nestedUpdatesCounter;
- },
-
- endUpdates: function()
- {
- if (!--this._nestedUpdatesCounter)
- this._codeMirror.refresh();
- },
-
- /**
- * @param {number} lineNumber
- */
- revealLine: function(lineNumber)
- {
- var pos = new CodeMirror.Pos(lineNumber, 0);
- var topLine = this._topScrolledLine();
- var bottomLine = this._bottomScrolledLine();
-
- var margin = null;
- var lineMargin = 3;
- var scrollInfo = this._codeMirror.getScrollInfo();
- if ((lineNumber < topLine + lineMargin) || (lineNumber >= bottomLine - lineMargin)) {
- // scrollIntoView could get into infinite loop if margin exceeds half of the clientHeight.
- margin = (scrollInfo.clientHeight*0.9/2) >>> 0;
- }
- this._codeMirror.scrollIntoView(pos, margin);
- },
-
- _gutterClick: function(instance, lineNumber, gutter, event)
- {
- this.dispatchEventToListeners(WebInspector.TextEditor.Events.GutterClick, { lineNumber: lineNumber, event: event });
- },
-
- _contextMenu: function(event)
- {
- var contextMenu = new WebInspector.ContextMenu(event);
- var target = event.target.enclosingNodeOrSelfWithClass("CodeMirror-gutter-elt");
- if (target)
- this._delegate.populateLineGutterContextMenu(contextMenu, parseInt(target.textContent, 10) - 1);
- else
- this._delegate.populateTextAreaContextMenu(contextMenu, 0);
- contextMenu.show();
- },
-
- /**
- * @param {number} lineNumber
- * @param {boolean} disabled
- * @param {boolean} conditional
- */
- addBreakpoint: function(lineNumber, disabled, conditional)
- {
- var className = "cm-breakpoint" + (conditional ? " cm-breakpoint-conditional" : "") + (disabled ? " cm-breakpoint-disabled" : "");
- this._codeMirror.addLineClass(lineNumber, "wrap", className);
- },
-
- /**
- * @param {number} lineNumber
- */
- removeBreakpoint: function(lineNumber)
- {
- var wrapClasses = this._codeMirror.getLineHandle(lineNumber).wrapClass;
- if (!wrapClasses)
- return;
- var classes = wrapClasses.split(" ");
- for(var i = 0; i < classes.length; ++i) {
- if (classes[i].startsWith("cm-breakpoint"))
- this._codeMirror.removeLineClass(lineNumber, "wrap", classes[i]);
- }
- },
-
- /**
- * @param {number} lineNumber
- */
- setExecutionLine: function(lineNumber)
- {
- this._executionLine = this._codeMirror.getLineHandle(lineNumber);
- this._codeMirror.addLineClass(this._executionLine, "wrap", "cm-execution-line");
- },
-
- clearExecutionLine: function()
- {
- if (this._executionLine)
- this._codeMirror.removeLineClass(this._executionLine, "wrap", "cm-execution-line");
- delete this._executionLine;
- },
-
- /**
- * @param {number} lineNumber
- * @param {Element} element
- */
- addDecoration: function(lineNumber, element)
- {
- var widget = this._codeMirror.addLineWidget(lineNumber, element);
- this._elementToWidget.put(element, widget);
- },
-
- /**
- * @param {number} lineNumber
- * @param {Element} element
- */
- removeDecoration: function(lineNumber, element)
- {
- var widget = this._elementToWidget.remove(element);
- if (widget)
- this._codeMirror.removeLineWidget(widget);
- },
-
- /**
- * @param {WebInspector.TextRange} range
- */
- markAndRevealRange: function(range)
- {
- if (range)
- this.setSelection(range);
- },
-
- /**
- * @param {number} lineNumber
- */
- highlightLine: function(lineNumber)
- {
- this.clearLineHighlight();
- this._highlightedLine = this._codeMirror.getLineHandle(lineNumber);
- if (!this._highlightedLine)
- return;
- this.revealLine(lineNumber);
- this._codeMirror.addLineClass(this._highlightedLine, null, "cm-highlight");
- this._clearHighlightTimeout = setTimeout(this.clearLineHighlight.bind(this), 2000);
- },
-
- clearLineHighlight: function()
- {
- if (this._clearHighlightTimeout)
- clearTimeout(this._clearHighlightTimeout);
- delete this._clearHighlightTimeout;
-
- if (this._highlightedLine)
- this._codeMirror.removeLineClass(this._highlightedLine, null, "cm-highlight");
- delete this._highlightedLine;
- },
-
- /**
- * @return {Array.<Element>}
- */
- elementsToRestoreScrollPositionsFor: function()
- {
- return [];
- },
-
- /**
- * @param {WebInspector.TextEditor} textEditor
- */
- inheritScrollPositions: function(textEditor)
- {
- },
-
- onResize: function()
- {
- this._codeMirror.refresh();
- },
-
- /**
- * @param {WebInspector.TextRange} range
- * @param {string} text
- * @return {WebInspector.TextRange}
- */
- editRange: function(range, text)
- {
- var pos = this._toPos(range);
- this._codeMirror.replaceRange(text, pos.start, pos.end);
- var newRange = this._toRange(pos.start, this._codeMirror.posFromIndex(this._codeMirror.indexFromPos(pos.start) + text.length));
- this._delegate.onTextChanged(range, newRange);
- return newRange;
- },
-
- _change: function()
- {
- var widgets = this._elementToWidget.values();
- for (var i = 0; i < widgets.length; ++i)
- this._codeMirror.removeLineWidget(widgets[i]);
- this._elementToWidget.clear();
-
- var newRange = this.range();
- if (!this._muteTextChangedEvent)
- this._delegate.onTextChanged(this._lastRange, newRange);
- this._lastRange = newRange;
- },
-
- _cursorActivity: function()
- {
- var start = this._codeMirror.getCursor("anchor");
- var end = this._codeMirror.getCursor("head");
- this._delegate.selectionChanged(this._toRange(start, end));
- },
-
- _coordsCharLocal: function(coords)
- {
- var top = coords.top;
- var totalLines = this._codeMirror.lineCount();
- var begin = 0;
- var end = totalLines - 1;
- while (end - begin > 1) {
- var middle = (begin + end) >> 1;
- coords = this._codeMirror.charCoords(new CodeMirror.Pos(middle, 0), "local");
- if (coords.top >= top)
- end = middle;
- else
- begin = middle;
- }
-
- return end;
- },
-
- _topScrolledLine: function()
- {
- var scrollInfo = this._codeMirror.getScrollInfo();
- // Workaround for CodeMirror's coordsChar incorrect result for "local" mode.
- return this._coordsCharLocal(scrollInfo);
- },
-
- _bottomScrolledLine: function()
- {
- var scrollInfo = this._codeMirror.getScrollInfo();
- scrollInfo.top += scrollInfo.clientHeight;
- // Workaround for CodeMirror's coordsChar incorrect result for "local" mode.
- return this._coordsCharLocal(scrollInfo);
- },
-
- _scroll: function()
- {
- this._delegate.scrollChanged(this._topScrolledLine());
- },
-
- /**
- * @param {number} lineNumber
- */
- scrollToLine: function(lineNumber)
- {
- function performScroll()
- {
- var pos = new CodeMirror.Pos(lineNumber, 0);
- var coords = this._codeMirror.charCoords(pos, "local");
- this._codeMirror.scrollTo(0, coords.top);
- }
-
- setTimeout(performScroll.bind(this), 0);
- },
-
- /**
- * @return {WebInspector.TextRange}
- */
- selection: function()
- {
- var start = this._codeMirror.getCursor(true);
- var end = this._codeMirror.getCursor(false);
-
- if (start.line > end.line || (start.line == end.line && start.ch > end.ch))
- return this._toRange(end, start);
-
- return this._toRange(start, end);
- },
-
- /**
- * @return {WebInspector.TextRange?}
- */
- lastSelection: function()
- {
- return this._lastSelection;
- },
-
- /**
- * @param {WebInspector.TextRange} textRange
- */
- setSelection: function(textRange)
- {
- function performSelectionSet()
- {
- this._lastSelection = textRange;
- var pos = this._toPos(textRange);
- this._codeMirror.setSelection(pos.start, pos.end);
- }
-
- setTimeout(performSelectionSet.bind(this), 0);
- },
-
- /**
- * @param {string} text
- */
- setText: function(text)
- {
- this._muteTextChangedEvent = true;
- this._codeMirror.setValue(text);
- this._codeMirror.clearHistory();
- delete this._muteTextChangedEvent;
- },
-
- /**
- * @return {string}
- */
- text: function()
- {
- return this._codeMirror.getValue();
- },
-
- /**
- * @return {WebInspector.TextRange}
- */
- range: function()
- {
- var lineCount = this.linesCount;
- var lastLine = this._codeMirror.getLine(lineCount - 1);
- return this._toRange(new CodeMirror.Pos(0, 0), new CodeMirror.Pos(lineCount - 1, lastLine.length));
- },
-
- /**
- * @param {number} lineNumber
- * @return {string}
- */
- line: function(lineNumber)
- {
- return this._codeMirror.getLine(lineNumber);
- },
-
- /**
- * @return {number}
- */
- get linesCount()
- {
- return this._codeMirror.lineCount();
- },
-
- /**
- * @param {number} line
- * @param {string} name
- * @param {Object?} value
- */
- setAttribute: function(line, name, value)
- {
- var handle = this._codeMirror.getLineHandle(line);
- if (handle.attributes === undefined) handle.attributes = {};
- handle.attributes[name] = value;
- },
-
- /**
- * @param {number} line
- * @param {string} name
- * @return {Object|null} value
- */
- getAttribute: function(line, name)
- {
- var handle = this._codeMirror.getLineHandle(line);
- return handle.attributes && handle.attributes[name] !== undefined ? handle.attributes[name] : null;
- },
-
- /**
- * @param {number} line
- * @param {string} name
- */
- removeAttribute: function(line, name)
- {
- var handle = this._codeMirror.getLineHandle(line);
- if (handle && handle.attributes)
- delete handle.attributes[name];
- },
-
- /**
- * @param {WebInspector.TextRange} range
- * @return {{start: CodeMirror.Pos, end: CodeMirror.Pos}}
- */
- _toPos: function(range)
- {
- return {
- start: new CodeMirror.Pos(range.startLine, range.startColumn),
- end: new CodeMirror.Pos(range.endLine, range.endColumn)
- }
- },
-
- _toRange: function(start, end)
- {
- return new WebInspector.TextRange(start.line, start.ch, end.line, end.ch);
- },
-
- __proto__: WebInspector.View.prototype
-}
-
-/**
- * @constructor
- * @param {CodeMirror} codeMirror
- */
-WebInspector.CodeMirrorTextEditor.TokenHighlighter = function(codeMirror)
-{
- this._codeMirror = codeMirror;
- this._codeMirror.on("cursorActivity", this._cursorChange.bind(this));
-}
-
-WebInspector.CodeMirrorTextEditor.TokenHighlighter.prototype = {
- _cursorChange: function()
- {
- this._codeMirror.operation(this._removeHighlight.bind(this));
- var selectionStart = this._codeMirror.getCursor("start");
- var selectionEnd = this._codeMirror.getCursor("end");
- if (selectionStart.line !== selectionEnd.line)
- return;
- if (selectionStart.ch === selectionEnd.ch)
- return;
-
- var selectedText = this._codeMirror.getSelection();
- if (this._isWord(selectedText, selectionStart.line, selectionStart.ch, selectionEnd.ch))
- this._codeMirror.operation(this._addHighlight.bind(this, selectedText, selectionStart));
- },
-
- _isWord: function(selectedText, lineNumber, startColumn, endColumn)
- {
- var line = this._codeMirror.getLine(lineNumber);
- var leftBound = startColumn === 0 || !WebInspector.TextUtils.isWordChar(line.charAt(startColumn - 1));
- var rightBound = endColumn === line.length || !WebInspector.TextUtils.isWordChar(line.charAt(endColumn));
- return leftBound && rightBound && WebInspector.TextUtils.isWord(selectedText);
- },
-
- _removeHighlight: function()
- {
- if (this._highlightDescriptor) {
- this._codeMirror.removeOverlay(this._highlightDescriptor.overlay);
- this._codeMirror.removeLineClass(this._highlightDescriptor.selectionStart.line, "wrap", "cm-line-with-selection");
- delete this._highlightDescriptor;
- }
- },
-
- _addHighlight: function(token, selectionStart)
- {
- const tokenFirstChar = token.charAt(0);
- /**
- * @param {CodeMirror.StringStream} stream
- */
- function nextToken(stream)
- {
- if (stream.match(token) && (stream.eol() || !WebInspector.TextUtils.isWordChar(stream.peek())))
- return stream.column() === selectionStart.ch ? "token-highlight column-with-selection" : "token-highlight";
-
- var eatenChar;
- do {
- eatenChar = stream.next();
- } while (eatenChar && (WebInspector.TextUtils.isWordChar(eatenChar) || stream.peek() !== tokenFirstChar));
- }
-
- var overlayMode = {
- token: nextToken
- };
- this._codeMirror.addOverlay(overlayMode);
- this._codeMirror.addLineClass(selectionStart.line, "wrap", "cm-line-with-selection")
- this._highlightDescriptor = {
- overlay: overlayMode,
- selectionStart: selectionStart
- };
- }
-}
-
-/**
- * @constructor
- * @param {CodeMirror} codeMirror
- */
-WebInspector.CodeMirrorTextEditor.BlockIndentController = function(codeMirror)
-{
- codeMirror.addKeyMap(this);
-}
-
-WebInspector.CodeMirrorTextEditor.BlockIndentController.prototype = {
- name: "blockIndentKeymap",
-
- Enter: function(codeMirror)
- {
- if (codeMirror.somethingSelected())
- return CodeMirror.Pass;
- var cursor = codeMirror.getCursor();
- var line = codeMirror.getLine(cursor.line);
- if (line.substr(cursor.ch - 1, 2) === "{}") {
- codeMirror.execCommand("newlineAndIndent");
- codeMirror.setCursor(cursor);
- codeMirror.execCommand("newlineAndIndent");
- codeMirror.execCommand("indentMore");
- } else if (line.substr(cursor.ch-1, 1) === "{") {
- codeMirror.execCommand("newlineAndIndent");
- codeMirror.execCommand("indentMore");
- } else
- return CodeMirror.Pass;
- },
-
- "'}'": function(codeMirror)
- {
- var cursor = codeMirror.getCursor();
- var line = codeMirror.getLine(cursor.line);
- for(var i = 0 ; i < line.length; ++i)
- if (!WebInspector.TextUtils.isSpaceChar(line.charAt(i)))
- return CodeMirror.Pass;
-
- codeMirror.replaceRange("}", cursor);
- var matchingBracket = codeMirror.findMatchingBracket();
- if (!matchingBracket.match)
- return;
-
- line = codeMirror.getLine(matchingBracket.to.line);
- var desiredIndentation = 0;
- while (desiredIndentation < line.length && WebInspector.TextUtils.isSpaceChar(line.charAt(desiredIndentation)))
- ++desiredIndentation;
-
- codeMirror.replaceRange(line.substr(0, desiredIndentation) + "}", new CodeMirror.Pos(cursor.line, 0), new CodeMirror.Pos(cursor.line, cursor.ch + 1));
- }
-}
-
-/**
- * @constructor
- * @param {CodeMirror} codeMirror
- */
-WebInspector.CodeMirrorTextEditor.FixWordMovement = function(codeMirror)
-{
- function moveLeft(shift, codeMirror)
- {
- var cursor = codeMirror.getCursor("head");
- if (cursor.ch !== 0 || cursor.line === 0)
- return CodeMirror.Pass;
- codeMirror.setExtending(shift);
- codeMirror.execCommand("goLineUp");
- codeMirror.execCommand("goLineEnd")
- codeMirror.setExtending(false);
- }
- function moveRight(shift, codeMirror)
- {
- var cursor = codeMirror.getCursor("head");
- var line = codeMirror.getLine(cursor.line);
- if (cursor.ch !== line.length || cursor.line + 1 === codeMirror.lineCount())
- return CodeMirror.Pass;
- codeMirror.setExtending(shift);
- codeMirror.execCommand("goLineDown");
- codeMirror.execCommand("goLineStart");
- codeMirror.setExtending(false);
- }
-
- var modifierKey = WebInspector.isMac() ? "Alt" : "Ctrl";
- var leftKey = modifierKey + "-Left";
- var rightKey = modifierKey + "-Right";
- var keyMap = {};
- keyMap[leftKey] = moveLeft.bind(this, false);
- keyMap[rightKey] = moveRight.bind(this, false);
- keyMap["Shift-" + leftKey] = moveLeft.bind(this, true);
- keyMap["Shift-" + rightKey] = moveRight.bind(this, true);
- codeMirror.addKeyMap(keyMap);
-}
+window.CodeMirror=(function(){"use strict";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);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]);if(opera_version&&opera_version>=15){opera=false;webkit=true;}
+var flipCtrlCmd=mac&&(qtwebkit||opera&&(opera_version==null||opera_version<12.11));var captureMiddleClick=gecko||(ie&&!ie_lt9);var sawReadOnlySpans=false,sawCollapsedSpans=false;function CodeMirror(place,options){if(!(this instanceof CodeMirror))return new CodeMirror(place,options);this.options=options=options||{};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);if(ie)setTimeout(bind(resetInput,this,true),20);registerEventHandlers(this);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);})();}
+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(ios)input.style.border="1px solid black";input.setAttribute("autocorrect","off");input.setAttribute("autocapitalize","off");input.setAttribute("spellcheck","false");d.inputDiv=elt("div",[input],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");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");d.lineDiv=elt("div",null,"CodeMirror-code");d.selectionDiv=elt("div",null,null,"position: relative; z-index: 1");d.cursor=elt("div","\u00a0","CodeMirror-cursor");d.otherCursor=elt("div","\u00a0","CodeMirror-cursor CodeMirror-secondarycursor");d.measure=elt("div",null,"CodeMirror-measure");d.lineSpace=elt("div",[d.measure,d.selectionDiv,d.lineDiv,d.cursor,d.otherCursor],null,"position: relative; outline: none");d.mover=elt("div",[elt("div",[d.lineSpace],"CodeMirror-lines")],null,"position: relative");d.sizer=elt("div",[d.mover],"CodeMirror-sizer");d.heightForcer=elt("div",null,null,"position: absolute; height: "+scrollerCutOff+"px; width: 1px;");d.gutters=elt("div",null,"CodeMirror-gutters");d.lineGutter=null;d.scroller=elt("div",[d.sizer,d.heightForcer,d.gutters],"CodeMirror-scroll");d.scroller.setAttribute("tabIndex","-1");d.wrapper=elt("div",[d.inputDiv,d.scrollbarH,d.scrollbarV,d.scrollbarFiller,d.gutterFiller,d.scroller],"CodeMirror");if(ie_lt8){d.gutters.style.zIndex=-1;d.scroller.style.paddingRight=0;}
+if(place.appendChild)place.appendChild(d.wrapper);else place(d.wrapper);if(ios)input.style.width="0px";if(!webkit)d.scroller.draggable=true;if(khtml){d.inputDiv.style.height="1px";d.inputDiv.style.position="absolute";}
+else if(ie_lt8)d.scrollbarH.style.minWidth=d.scrollbarV.style.minWidth="18px";d.viewOffset=d.lastSizeC=0;d.showingFrom=d.showingTo=docStart;d.lineNumWidth=d.lineNumInnerWidth=d.lineNumChars=null;d.prevInput="";d.alignWidgets=false;d.pollingFast=false;d.poll=new Delayed();d.cachedCharWidth=d.cachedTextHeight=null;d.measureLineCache=[];d.measureLineCachePos=0;d.inaccurateSelection=false;d.maxLine=null;d.maxLineLength=0;d.maxLineChanged=false;d.wheelDX=d.wheelDY=d.wheelStartX=d.wheelStartY=null;return d;}
+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;}});}
+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");}
+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)};}
+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;}
+function updateDisplay(cm,changes,viewPort,forced){var oldFrom=cm.display.showingFrom,oldTo=cm.display.showingTo,updated;var visible=visibleLines(cm.display,cm.doc,viewPort);for(;;){if(!updateDisplayInner(cm,changes,visible,forced))break;forced=false;updated=true;updateSelection(cm);updateScrollbars(cm);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;}
+function updateDisplayInner(cm,changes,visible,forced){var display=cm.display,doc=cm.doc;if(!display.wrapper.clientWidth){display.showingFrom=display.showingTo=doc.first;display.viewOffset=0;return;}
+if(!forced&&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";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;}
+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);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;}}}
+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(!forced&&intactLines==to-from&&from==display.showingFrom&&to==display.showingTo){updateViewOffset(cm);return;}
+intact.sort(function(a,b){return a.from-b.from;});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;if(different){display.lastSizeC=display.wrapper.clientHeight;startWorker(cm,400);}
+display.showingFrom=from;display.showingTo=to;updateHeightsInViewport(cm);updateViewOffset(cm);return true;}
+function updateHeightsInViewport(cm){var display=cm.display;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;}}}
+function updateViewOffset(cm){var off=cm.display.viewOffset=heightAtLine(cm,getLine(cm.doc,cm.display.showingFrom));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){while(cur.lineObj!=line)cur=rm(cur);if(lineNumbers&&updateNumbersFrom<=lineN&&cur.lineNumber)
+setTextContent(cur.lineNumber,lineNumberFor(cm.options,lineN));cur=cur.nextSibling;}else{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;}
+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;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;i<line.widgets.length;++i){var widget=line.widgets[i];if(widget.node==n.firstChild){if(!widget.above&&!insertBefore)insertBefore=n;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);}
+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";}}
+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";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";}}
+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";}}
+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){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="";}
+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);}
+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){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);})();}
+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;}
+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.get(pos);if(r)break;if(dir<0&&pos==0)dir=1;}
+bias=pos>ch?"left":pos<ch?"right":bias;if(bias=="left"&&r.leftSide)r=r.leftSide;else if(bias=="right"&&r.rightSide)r=r.rightSide;return{left:pos<ch?r.right:r.left,right:pos>ch?r.left:r.right,top:r.top,bottom: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){var cached=findCachedMeasurement(cm,line);if(cached)return cached.measure;var measure=measureLineInner(cm,line,0,10);measure.get=function(num){if(this[num])return this[num];if(num<0||num>=line.text.length)return null;measureLineInner(cm,line,Math.max(num-50,0),Math.min(num+50,line.text.length),this);return this[num];};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,from,to,oldMeasure){var display=cm.display,measure=emptyArray(line.text.length);var pre=lineContent(cm,line,measure,true,from,to);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=oldMeasure||emptyArray(line.text.length),maxBot=pre.offsetHeight;if(ie_lt9&&display.measure.first!=pre)
+removeChildrenAndAdd(display.measure,pre);function measureRect(rect){var top=rect.top-outer.top,bot=rect.bottom-outer.top;if(bot>maxBot)bot=maxBot;if(top<0)top=0;for(var i=vranges.length-2;i>=0;i-=2){var rtop=vranges[i],rbot=vranges[i+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[i]=Math.min(top,rtop);vranges[i+1]=Math.max(bot,rbot);break;}}
+if(i<0){i=vranges.length;vranges.push(top,bot);}
+return{left:rect.left-outer.left,right:rect.right-outer.left,top:i,bottom:null};}
+function finishRect(rect){rect.bottom=vranges[rect.top+1];rect.top=vranges[rect.top];}
+for(var i=0,cur;i<measure.length;++i)if(cur=measure[i]){var node=cur,rect=null;if(/\bCodeMirror-widget\b/.test(cur.className)&&cur.getClientRects){if(cur.firstChild.nodeType==1)node=cur.firstChild;var rects=node.getClientRects();if(rects.length>1){rect=data[i]=measureRect(rects[0]);rect.rightSide=measureRect(rects[rects.length-1]);}}
+if(!rect)rect=data[i]=measureRect(getRect(node));if(cur.measureRight)rect.right=getRect(cur.measureRight).left;if(cur.leftSide)rect.leftSide=measureRect(getRect(cur.leftSide));}
+for(var i=0,cur;i<data.length;++i)if(measure[i]&&(cur=data[i])){finishRect(cur);if(cur.leftSide)finishRect(cur.leftSide);if(cur.rightSide)finishRect(cur.rightSide);}
+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,null,true);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;}
+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;}
+function fromCoordSystem(cm,coords,context){if(context=="div")return coords;var left=coords.left,top=coords.top;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;}
+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);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");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;}
+var nextOpId=0;function startOperation(cm){cm.curOp={changes:[],forceUpdate:false,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){var coords=cursorCoords(cm,doc.sel.head);newScrollPos=calculateScrollPos(cm,coords.left,coords.top,coords.left,coords.bottom);}
+if(op.changes.length||op.forceUpdate||newScrollPos&&newScrollPos.scrollTop!=null){updated=updateDisplay(cm,op.changes,newScrollPos&&newScrollPos.scrollTop,op.forceUpdate);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]();}
+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});}
+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);}
+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;if(cm.state.pasteIncoming&&cm.state.fakedLastChar){input.value=input.value.substring(0,input.value.length-1);cm.state.fakedLastChar=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;}
+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);});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);on(d.wrapper,"scroll",function(){d.wrapper.scrollTop=d.wrapper.scrollLeft=0;});var resizeTimer;function onResize(){if(resizeTimer==null)resizeTimer=setTimeout(function(){resizeTimer=null;d.cachedCharWidth=d.cachedTextHeight=knownScrollbarWidth=null;clearCaches(cm);runInOp(cm,bind(regChange,cm));},100);}
+on(window,"resize",onResize);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(){if(webkit&&!cm.state.fakedLastChar){var start=d.input.selectionStart,end=d.input.selectionEnd;d.input.value+="$";d.input.selectionStart=start;d.input.selectionEnd=end;cm.state.fakedLastChar=true;}
+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);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);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;}
+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);}});if(webkit)display.scroller.draggable=true;cm.state.draggingText=dragEnd;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);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;}
+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{if(cm.state.draggingText&&!(posLess(pos,cm.doc.sel.from)||posLess(cm.doc.sel.to,pos))){cm.state.draggingText(e);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);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);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;}
+var wheelSamples=0,wheelPixelsPerUnit=null;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;if(!(dx&&scroll.scrollWidth>scroll.clientWidth||dy&&scroll.scrollHeight>scroll.clientHeight))return;if(dy&&mac&&webkit){for(var cur=e.target;cur!=scroll;cur=cur.parentNode){if(cur.lineObj){cm.display.currentWheelTarget=cur;break;}}}
+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;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;}
+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){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){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;cm.doc.sel.shift=code==16||e.shiftKey;var handled=handleKeyBinding(cm,e);if(opera){lastStoppedKey=handled?code:null;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){if(signalDOMEvent(cm,e,"contextmenu"))return;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;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);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);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);}}
+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));};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));}
+function computeSelAfterChange(doc,change,hint){if(hint&&typeof hint=="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};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};}
+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;}
+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;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;}
+doc.frontier=Math.min(doc.frontier,from.line);startWorker(cm,400);var lendiff=change.text.length-(to.line-from.line)-1;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);}
+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);}
+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;}
+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;}
+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;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){if(!mayClear)return skipAtomic(doc,pos,bias,true);doc.cantEdit=true;return Pos(doc.first,0);}
+flipped=true;newPos=pos;dir=-dir;}}
+curPos=newPos;continue search;}}}
+return curPos;}}
+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));}
+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)--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)));}
+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(maps[i]==map||(typeof maps[i]!="string"&&maps[i].name==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);}),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,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;if(ch==0)return styles[2];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];}},getModeAt:function(pos){var mode=this.doc.mode;if(!mode.innerMode)return mode;return CodeMirror.innerMode(mode,this.getTokenAt(pos).state).mode;},getHelper:function(pos,type){if(!helpers.hasOwnProperty(type))return;var help=helpers[type],mode=this.getModeAt(pos);return mode[type]&&help[mode[type]]||mode.helperType&&help[mode.helperType]||help[mode.name];},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);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:operation(null,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);if(this.options.lineWrapping)
+this.display.measureLineCache.length=this.display.measureLineCachePos=0;this.curOp.forceUpdate=true;}),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;}};eventMixin(CodeMirror);var optionHandlers=CodeMirror.optionHandlers={};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";}};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);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){var 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);};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);};var helpers=CodeMirror.helpers={};CodeMirror.registerHelper=function(type,name,value){if(!helpers.hasOwnProperty(type))helpers[type]=CodeMirror[type]={};helpers[type][name]=value;};CodeMirror.isWordChar=isWordChar;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);if(!info||info.mode==mode)break;state=info.state;mode=info.mode;}
+return info||{mode:mode,state:state};};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();}};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"};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"};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;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;if(options.autofocus==null){var hasFocus=document.body;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);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;};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;function TextMarker(doc,type){this.lines=[];this.type=type;this.doc=doc;}
+CodeMirror.TextMarker=TextMarker;eventMixin(TextMarker);TextMarker.prototype.clear=function(){if(this.explicitlyCleared)return;var cm=this.doc.cm,withOp=cm&&!cm.curOp;if(withOp)startOperation(cm);if(hasHandler(this,"clear")){var found=this.find();if(found)signalLater(this,"clear",found.from,found.to);}
+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);};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;if(this.type!="bookmark")pos=pos.from;var line=getLine(this.doc,pos.line);clearCachedMeasurement(cm,line);if(pos.line>=cm.display.showingFrom&&pos.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=cm.curOp.forceUpdate=cm.curOp.updateMaxLine=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.title||marker.startStyle||marker.endStyle||marker.collapsed)
+regChange(cm,from.line,to.line+1);if(marker.atomic)reCheckSelection(cm);}
+return marker;}
+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;eventMixin(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);}
+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);var first=markedSpansBefore(oldFirst,startCh,isInsert);var last=markedSpansAfter(oldLast,endCh,isInsert);var sameLine=change.text.length==1,offset=lst(change.text).length+(sameLine?startCh:0);if(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){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){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){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;}
+var LineWidget=CodeMirror.LineWidget=function(cm,node,options){if(options)for(var opt in options)if(options.hasOwnProperty(opt))
+this[opt]=options[opt];this.cm=cm;this.node=node;};eventMixin(LineWidget);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;var aboveVisible=heightAtLine(this.cm,this.line)<this.cm.doc.scrollTop;updateLineHeight(this.line,Math.max(0,this.line.height-widgetHeight(this)));if(aboveVisible)addToScrollPos(this.cm,0,-this.height);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){var widgets=line.widgets||(line.widgets=[]);if(widget.insertAt==null)widgets.push(widget);else widgets.splice(Math.min(widgets.length-1,Math.max(0,widget.insertAt)),0,widget);widget.line=line;if(!lineIsHidden(cm.doc,line)||widget.showIfHidden){var aboveVisible=heightAtLine(cm,line)<cm.doc.scrollTop;updateLineHeight(line,line.height+widgetHeight(widget));if(aboveVisible)addToScrollPos(cm,0,widget.height);}
+return true;});return widget;}
+var Line=CodeMirror.Line=function(text,markedSpans,estimateHeight){this.text=text;attachMarkedSpans(this,markedSpans);this.height=estimateHeight?estimateHeight(this):1;};eventMixin(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);}
+function runMode(cm,text,mode,state,f){var flattenSpans=mode.flattenSpans;if(flattenSpans==null)flattenSpans=cm.options.flattenSpans;var curStart=0,curStyle=null;var stream=new StringStream(text,cm.options.tabSize),style;if(text==""&&mode.blankLine)mode.blankLine(state);while(!stream.eol()){if(stream.pos>cm.options.maxHighlightLength){flattenSpans=false;stream.pos=Math.min(text.length,stream.start+50000);style=null;}else{style=mode.token(stream,state);}
+if(!flattenSpans||curStyle!=style){if(curStart<stream.start)f(stream.start,curStyle);curStart=stream.start;curStyle=style;}
+stream.start=stream.pos;}
+if(curStart<stream.pos)f(stream.pos,curStyle);}
+function highlightLine(cm,line,state){var st=[cm.state.modeGen];runMode(cm,line.text,cm.doc.mode,state,function(end,style){st.push(end,style);});for(var o=0;o<cm.state.overlays.length;++o){var overlay=cm.state.overlays[o],i=1,at=0;runMode(cm,line.text,overlay.mode,true,function(end,style){var start=i;while(at<end){var i_end=st[i];if(i_end>end)
+st.splice(i,1,end,st[i+1],i_end);i+=2;at=Math.min(end,i_end);}
+if(!style)return;if(overlay.opaque){st.splice(start,i-start,end,style);i=start+2;}else{for(;start<i;start+=2){var cur=st[start+1];st[start+1]=cur?cur+" "+style:style;}}});}
+return st;}
+function getLineStyles(cm,line){if(!line.styles||line.styles[0]!=cm.state.modeGen)
+line.styles=highlightLine(cm,line,line.stateAfter=getStateBefore(cm,lineNo(line)));return line.styles;}
+function processLine(cm,line,state){var mode=cm.doc.mode;var stream=new StringStream(line.text,cm.options.tabSize);if(line.text==""&&mode.blankLine)mode.blankLine(state);while(!stream.eol()&&stream.pos<=cm.options.maxHighlightLength){mode.token(stream,state);stream.start=stream.pos;}}
+var styleToClassCache={};function styleToClass(style){if(!style)return null;return styleToClassCache[style]||(styleToClassCache[style]="cm-"+style.replace(/ +/g," cm-"));}
+function lineContent(cm,realLine,measure,copyWidgets,from,to){var merged,line=realLine,empty=true;while(merged=collapsedSpanAtStart(line))
+line=getLine(cm.doc,merged.find().from.line);var builder={pre:elt("pre"),col:0,pos:0,measure:null,measuredSomething:false,cm:cm,from:from,to:to,copyWidgets:copyWidgets};if(line.textClass)builder.pre.className=line.textClass;do{if(line.text)empty=false;builder.measure=line==realLine&&measure;builder.pos=0;builder.addToken=builder.measure?buildTokenMeasure:buildToken;if((ie||webkit)&&cm.getOption("lineWrapping"))
+builder.addToken=buildTokenSplitSpaces(builder.addToken);var next=insertLineContent(line,builder,getLineStyles(cm,line));if(measure&&line==realLine&&!builder.measuredSomething){measure[0]=builder.pre.appendChild(zeroWidthElement(cm.display.measure));builder.measuredSomething=true;}
+if(next)line=getLine(cm.doc,next.to.line);}while(next);if(measure&&!builder.measuredSomething&&!measure[0])
+measure[0]=builder.pre.appendChild(empty?elt("span","\u00a0"):zeroWidthElement(cm.display.measure));if(!builder.pre.firstChild&&!lineIsHidden(cm.doc,realLine))
+builder.pre.appendChild(document.createTextNode("\u00a0"));var order;if(measure&&ie&&(order=getOrder(line))){var l=order.length-1;if(order[l].from==order[l].to)--l;var last=order[l],prev=order[l-1];if(last.from+1==last.to&&prev&&last.level<prev.level){var span=measure[builder.pos-1];if(span)span.parentNode.insertBefore(span.measureRight=zeroWidthElement(cm.display.measure),span.nextSibling);}}
+signal(cm,"renderLine",cm,realLine,builder.pre);return builder.pre;}
+var tokenSpecialChars=/[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;function buildToken(builder,text,style,startStyle,endStyle,title){if(!text)return;if(!tokenSpecialChars.test(text)){builder.col+=text.length;var content=document.createTextNode(text);}else{var content=document.createDocumentFragment(),pos=0;while(true){tokenSpecialChars.lastIndex=pos;var m=tokenSpecialChars.exec(text);var skipped=m?m.index-pos:text.length-pos;if(skipped){content.appendChild(document.createTextNode(text.slice(pos,pos+skipped)));builder.col+=skipped;}
+if(!m)break;pos+=skipped+1;if(m[0]=="\t"){var tabSize=builder.cm.options.tabSize,tabWidth=tabSize-builder.col%tabSize;content.appendChild(elt("span",spaceStr(tabWidth),"cm-tab"));builder.col+=tabWidth;}else{var token=elt("span","\u2022","cm-invalidchar");token.title="\\u"+m[0].charCodeAt(0).toString(16);content.appendChild(token);builder.col+=1;}}}
+if(style||startStyle||endStyle||builder.measure){var fullStyle=style||"";if(startStyle)fullStyle+=startStyle;if(endStyle)fullStyle+=endStyle;var token=elt("span",[content],fullStyle);if(title)token.title=title;return builder.pre.appendChild(token);}
+builder.pre.appendChild(content);}
+function buildTokenMeasure(builder,text,style,startStyle,endStyle){if(builder.from||builder.to){if(builder.from>=builder.pos+text.length){buildToken(builder,text,style,startStyle,endStyle);builder.pos+=text.length;return;}}
+var wrapping=builder.cm.options.lineWrapping;for(var i=0;i<text.length;++i){var ch=text.charAt(i),start=i==0;if(ch>="\ud800"&&ch<"\udbff"&&i<text.length-1){ch=text.slice(i,i+2);++i;}else if(i&&wrapping&&spanAffectsWrapping(text,i)){builder.pre.appendChild(elt("wbr"));}
+var old=builder.measure[builder.pos];var span=builder.measure[builder.pos]=buildToken(builder,ch,style,start&&startStyle,i==text.length-1&&endStyle);if(old)span.leftSide=old.leftSide||old;if(ie&&wrapping&&ch==" "&&i&&!/\s/.test(text.charAt(i-1))&&i<text.length-1&&!/\s/.test(text.charAt(i+1)))
+span.style.whiteSpace="normal";builder.pos+=ch.length;}
+if(text.length)builder.measuredSomething=true;}
+function buildTokenSplitSpaces(inner){function split(old){var out=" ";for(var i=0;i<old.length-2;++i)out+=i%2?" ":"\u00a0";out+=" ";return out;}
+return function(builder,text,style,startStyle,endStyle,title){return inner(builder,text.replace(/ {3,}/,split),style,startStyle,endStyle,title);};}
+function buildCollapsedSpan(builder,size,marker,ignoreWidget){var widget=!ignoreWidget&&marker.replacedWith;if(widget){if(builder.copyWidgets)widget=widget.cloneNode(true);builder.pre.appendChild(widget);if(builder.measure){if(size){builder.measure[builder.pos]=widget;}else{var elt=builder.measure[builder.pos]=zeroWidthElement(builder.cm.display.measure);if(marker.type!="bookmark"||marker.insertLeft)
+builder.pre.insertBefore(elt,widget);else
+builder.pre.appendChild(elt);}
+builder.measuredSomething=true;}}
+builder.pos+=size;}
+function insertLineContent(line,builder,styles){var spans=line.markedSpans,allText=line.text,at=0;if(!spans){if(builder.to||builder.from){for(var i=1;i<styles.length&&(!builder.to||builder.pos<builder.to);i+=2){var text=allText.slice(at,at=styles[i]);var textLength=text.length;var resolvedStyles=styleToClass(styles[i+1]);if(builder.pos+textLength<=builder.from){builder.addToken(builder,text,resolvedStyles);continue;}
+if(builder.pos<builder.from&&builder.pos+textLength>builder.from){var overlap=builder.from-builder.pos;builder.addToken(builder,text.substring(0,overlap),resolvedStyles);text=text.substring(overlap);}
+builder.addToken(builder,text.substr(0,Math.min(builder.to-builder.from,text.length)),resolvedStyles);}}else{for(var i=1;i<styles.length;i+=2)
+builder.addToken(builder,allText.slice(at,at=styles[i]),styleToClass(styles[i+1]));}
+return;}
+var len=allText.length,pos=0,i=1,text="",style;var nextChange=0,spanStyle,spanEndStyle,spanStartStyle,title,collapsed;for(;;){if(nextChange==pos){spanStyle=spanEndStyle=spanStartStyle=title="";collapsed=null;nextChange=Infinity;var foundBookmarks=[];for(var j=0;j<spans.length;++j){var sp=spans[j],m=sp.marker;if(sp.from<=pos&&(sp.to==null||sp.to>pos)){if(sp.to!=null&&nextChange>sp.to){nextChange=sp.to;spanEndStyle="";}
+if(m.className)spanStyle+=" "+m.className;if(m.startStyle&&sp.from==pos)spanStartStyle+=" "+m.startStyle;if(m.endStyle&&sp.to==nextChange)spanEndStyle+=" "+m.endStyle;if(m.title&&!title)title=m.title;if(m.collapsed&&(!collapsed||collapsed.marker.size<m.size))
+collapsed=sp;}else if(sp.from>pos&&nextChange>sp.from){nextChange=sp.from;}
+if(m.type=="bookmark"&&sp.from==pos&&m.replacedWith)foundBookmarks.push(m);}
+if(collapsed&&(collapsed.from||0)==pos){buildCollapsedSpan(builder,(collapsed.to==null?len:collapsed.to)-pos,collapsed.marker,collapsed.from==null);if(collapsed.to==null)return collapsed.marker.find();}
+if(!collapsed&&foundBookmarks.length)for(var j=0;j<foundBookmarks.length;++j)
+buildCollapsedSpan(builder,0,foundBookmarks[j]);}
+if(pos>=len)break;var upto=Math.min(len,nextChange);while(true){if(text){var end=pos+text.length;if(!collapsed){var tokenText=end>upto?text.slice(0,upto-pos):text;builder.addToken(builder,tokenText,style?style+spanStyle:spanStyle,spanStartStyle,pos+tokenText.length==nextChange?spanEndStyle:"",title);if(builder.to&&builder.pos>=builder.to)
+return;}
+if(end>=upto){text=text.slice(upto-pos);pos=upto;break;}
+pos=end;spanStartStyle="";}
+text=allText.slice(at,at=styles[i++]);style=styleToClass(styles[i++]);}}}
+function updateDoc(doc,change,markedSpans,selAfter,estimateHeight){function spansFor(n){return markedSpans?markedSpans[n]:null;}
+function update(line,text,spans){updateLine(line,text,spans,estimateHeight);signalLater(line,"change",line,change);}
+var from=change.from,to=change.to,text=change.text;var firstLine=getLine(doc,from.line),lastLine=getLine(doc,to.line);var lastText=lst(text),lastSpans=spansFor(text.length-1),nlines=to.line-from.line;if(from.ch==0&&to.ch==0&&lastText==""){for(var i=0,e=text.length-1,added=[];i<e;++i)
+added.push(new Line(text[i],spansFor(i),estimateHeight));update(lastLine,lastLine.text,lastSpans);if(nlines)doc.remove(from.line,nlines);if(added.length)doc.insert(from.line,added);}else if(firstLine==lastLine){if(text.length==1){update(firstLine,firstLine.text.slice(0,from.ch)+lastText+firstLine.text.slice(to.ch),lastSpans);}else{for(var added=[],i=1,e=text.length-1;i<e;++i)
+added.push(new Line(text[i],spansFor(i),estimateHeight));added.push(new Line(lastText+firstLine.text.slice(to.ch),lastSpans,estimateHeight));update(firstLine,firstLine.text.slice(0,from.ch)+text[0],spansFor(0));doc.insert(from.line+1,added);}}else if(text.length==1){update(firstLine,firstLine.text.slice(0,from.ch)+text[0]+lastLine.text.slice(to.ch),spansFor(0));doc.remove(from.line+1,nlines);}else{update(firstLine,firstLine.text.slice(0,from.ch)+text[0],spansFor(0));update(lastLine,lastText+lastLine.text.slice(to.ch),lastSpans);for(var i=1,e=text.length-1,added=[];i<e;++i)
+added.push(new Line(text[i],spansFor(i),estimateHeight));if(nlines>1)doc.remove(from.line+1,nlines-1);doc.insert(from.line+1,added);}
+signalLater(doc,"change",doc,change);setSelection(doc,selAfter.anchor,selAfter.head,null,true);}
+function LeafChunk(lines){this.lines=lines;this.parent=null;for(var i=0,e=lines.length,height=0;i<e;++i){lines[i].parent=this;height+=lines[i].height;}
+this.height=height;}
+LeafChunk.prototype={chunkSize:function(){return this.lines.length;},removeInner:function(at,n){for(var i=at,e=at+n;i<e;++i){var line=this.lines[i];this.height-=line.height;cleanUpLine(line);signalLater(line,"delete");}
+this.lines.splice(at,n);},collapse:function(lines){lines.splice.apply(lines,[lines.length,0].concat(this.lines));},insertInner:function(at,lines,height){this.height+=height;this.lines=this.lines.slice(0,at).concat(lines).concat(this.lines.slice(at));for(var i=0,e=lines.length;i<e;++i)lines[i].parent=this;},iterN:function(at,n,op){for(var e=at+n;at<e;++at)
+if(op(this.lines[at]))return true;}};function BranchChunk(children){this.children=children;var size=0,height=0;for(var i=0,e=children.length;i<e;++i){var ch=children[i];size+=ch.chunkSize();height+=ch.height;ch.parent=this;}
+this.size=size;this.height=height;this.parent=null;}
+BranchChunk.prototype={chunkSize:function(){return this.size;},removeInner:function(at,n){this.size-=n;for(var i=0;i<this.children.length;++i){var child=this.children[i],sz=child.chunkSize();if(at<sz){var rm=Math.min(n,sz-at),oldHeight=child.height;child.removeInner(at,rm);this.height-=oldHeight-child.height;if(sz==rm){this.children.splice(i--,1);child.parent=null;}
+if((n-=rm)==0)break;at=0;}else at-=sz;}
+if(this.size-n<25){var lines=[];this.collapse(lines);this.children=[new LeafChunk(lines)];this.children[0].parent=this;}},collapse:function(lines){for(var i=0,e=this.children.length;i<e;++i)this.children[i].collapse(lines);},insertInner:function(at,lines,height){this.size+=lines.length;this.height+=height;for(var i=0,e=this.children.length;i<e;++i){var child=this.children[i],sz=child.chunkSize();if(at<=sz){child.insertInner(at,lines,height);if(child.lines&&child.lines.length>50){while(child.lines.length>50){var spilled=child.lines.splice(child.lines.length-25,25);var newleaf=new LeafChunk(spilled);child.height-=newleaf.height;this.children.splice(i+1,0,newleaf);newleaf.parent=this;}
+this.maybeSpill();}
+break;}
+at-=sz;}},maybeSpill:function(){if(this.children.length<=10)return;var me=this;do{var spilled=me.children.splice(me.children.length-5,5);var sibling=new BranchChunk(spilled);if(!me.parent){var copy=new BranchChunk(me.children);copy.parent=me;me.children=[copy,sibling];me=copy;}else{me.size-=sibling.size;me.height-=sibling.height;var myIndex=indexOf(me.parent.children,me);me.parent.children.splice(myIndex+1,0,sibling);}
+sibling.parent=me.parent;}while(me.children.length>10);me.parent.maybeSpill();},iterN:function(at,n,op){for(var i=0,e=this.children.length;i<e;++i){var child=this.children[i],sz=child.chunkSize();if(at<sz){var used=Math.min(n,sz-at);if(child.iterN(at,used,op))return true;if((n-=used)==0)break;at=0;}else at-=sz;}}};var nextDocId=0;var Doc=CodeMirror.Doc=function(text,mode,firstLine){if(!(this instanceof Doc))return new Doc(text,mode,firstLine);if(firstLine==null)firstLine=0;BranchChunk.call(this,[new LeafChunk([new Line("",null)])]);this.first=firstLine;this.scrollTop=this.scrollLeft=0;this.cantEdit=false;this.history=makeHistory();this.cleanGeneration=1;this.frontier=firstLine;var start=Pos(firstLine,0);this.sel={from:start,to:start,head:start,anchor:start,shift:false,extend:false,goalColumn:null};this.id=++nextDocId;this.modeOption=mode;if(typeof text=="string")text=splitLines(text);updateDoc(this,{from:start,to:start,text:text},null,{head:start,anchor:start});};Doc.prototype=createObj(BranchChunk.prototype,{constructor:Doc,iter:function(from,to,op){if(op)this.iterN(from-this.first,to-from,op);else this.iterN(this.first,this.first+this.size,from);},insert:function(at,lines){var height=0;for(var i=0,e=lines.length;i<e;++i)height+=lines[i].height;this.insertInner(at-this.first,lines,height);},remove:function(at,n){this.removeInner(at-this.first,n);},getValue:function(lineSep){var lines=getLines(this,this.first,this.first+this.size);if(lineSep===false)return lines;return lines.join(lineSep||"\n");},setValue:function(code){var top=Pos(this.first,0),last=this.first+this.size-1;makeChange(this,{from:top,to:Pos(last,getLine(this,last).text.length),text:splitLines(code),origin:"setValue"},{head:top,anchor:top},true);},replaceRange:function(code,from,to,origin){from=clipPos(this,from);to=to?clipPos(this,to):from;replaceRange(this,code,from,to,origin);},getRange:function(from,to,lineSep){var lines=getBetween(this,clipPos(this,from),clipPos(this,to));if(lineSep===false)return lines;return lines.join(lineSep||"\n");},getLine:function(line){var l=this.getLineHandle(line);return l&&l.text;},setLine:function(line,text){if(isLine(this,line))
+replaceRange(this,text,Pos(line,0),clipPos(this,Pos(line)));},removeLine:function(line){if(line)replaceRange(this,"",clipPos(this,Pos(line-1)),clipPos(this,Pos(line)));else replaceRange(this,"",Pos(0,0),clipPos(this,Pos(1,0)));},getLineHandle:function(line){if(isLine(this,line))return getLine(this,line);},getLineNumber:function(line){return lineNo(line);},getLineHandleVisualStart:function(line){if(typeof line=="number")line=getLine(this,line);return visualLine(this,line);},lineCount:function(){return this.size;},firstLine:function(){return this.first;},lastLine:function(){return this.first+this.size-1;},clipPos:function(pos){return clipPos(this,pos);},getCursor:function(start){var sel=this.sel,pos;if(start==null||start=="head")pos=sel.head;else if(start=="anchor")pos=sel.anchor;else if(start=="end"||start===false)pos=sel.to;else pos=sel.from;return copyPos(pos);},somethingSelected:function(){return!posEq(this.sel.head,this.sel.anchor);},setCursor:docOperation(function(line,ch,extend){var pos=clipPos(this,typeof line=="number"?Pos(line,ch||0):line);if(extend)extendSelection(this,pos);else setSelection(this,pos,pos);}),setSelection:docOperation(function(anchor,head){setSelection(this,clipPos(this,anchor),clipPos(this,head||anchor));}),extendSelection:docOperation(function(from,to){extendSelection(this,clipPos(this,from),to&&clipPos(this,to));}),getSelection:function(lineSep){return this.getRange(this.sel.from,this.sel.to,lineSep);},replaceSelection:function(code,collapse,origin){makeChange(this,{from:this.sel.from,to:this.sel.to,text:splitLines(code),origin:origin},collapse||"around");},undo:docOperation(function(){makeChangeFromHistory(this,"undo");}),redo:docOperation(function(){makeChangeFromHistory(this,"redo");}),setExtending:function(val){this.sel.extend=val;},historySize:function(){var hist=this.history;return{undo:hist.done.length,redo:hist.undone.length};},clearHistory:function(){this.history=makeHistory(this.history.maxGeneration);},markClean:function(){this.cleanGeneration=this.changeGeneration();},changeGeneration:function(){this.history.lastOp=this.history.lastOrigin=null;return this.history.generation;},isClean:function(gen){return this.history.generation==(gen||this.cleanGeneration);},getHistory:function(){return{done:copyHistoryArray(this.history.done),undone:copyHistoryArray(this.history.undone)};},setHistory:function(histData){var hist=this.history=makeHistory(this.history.maxGeneration);hist.done=histData.done.slice(0);hist.undone=histData.undone.slice(0);},markText:function(from,to,options){return markText(this,clipPos(this,from),clipPos(this,to),options,"range");},setBookmark:function(pos,options){var realOpts={replacedWith:options&&(options.nodeType==null?options.widget:options),insertLeft:options&&options.insertLeft};pos=clipPos(this,pos);return markText(this,pos,pos,realOpts,"bookmark");},findMarksAt:function(pos){pos=clipPos(this,pos);var markers=[],spans=getLine(this,pos.line).markedSpans;if(spans)for(var i=0;i<spans.length;++i){var span=spans[i];if((span.from==null||span.from<=pos.ch)&&(span.to==null||span.to>=pos.ch))
+markers.push(span.marker.parent||span.marker);}
+return markers;},getAllMarks:function(){var markers=[];this.iter(function(line){var sps=line.markedSpans;if(sps)for(var i=0;i<sps.length;++i)
+if(sps[i].from!=null)markers.push(sps[i].marker);});return markers;},posFromIndex:function(off){var ch,lineNo=this.first;this.iter(function(line){var sz=line.text.length+1;if(sz>off){ch=off;return true;}
+off-=sz;++lineNo;});return clipPos(this,Pos(lineNo,ch));},indexFromPos:function(coords){coords=clipPos(this,coords);var index=coords.ch;if(coords.line<this.first||coords.ch<0)return 0;this.iter(this.first,coords.line,function(line){index+=line.text.length+1;});return index;},copy:function(copyHistory){var doc=new Doc(getLines(this,this.first,this.first+this.size),this.modeOption,this.first);doc.scrollTop=this.scrollTop;doc.scrollLeft=this.scrollLeft;doc.sel={from:this.sel.from,to:this.sel.to,head:this.sel.head,anchor:this.sel.anchor,shift:this.sel.shift,extend:false,goalColumn:this.sel.goalColumn};if(copyHistory){doc.history.undoDepth=this.history.undoDepth;doc.setHistory(this.getHistory());}
+return doc;},linkedDoc:function(options){if(!options)options={};var from=this.first,to=this.first+this.size;if(options.from!=null&&options.from>from)from=options.from;if(options.to!=null&&options.to<to)to=options.to;var copy=new Doc(getLines(this,from,to),options.mode||this.modeOption,from);if(options.sharedHist)copy.history=this.history;(this.linked||(this.linked=[])).push({doc:copy,sharedHist:options.sharedHist});copy.linked=[{doc:this,isParent:true,sharedHist:options.sharedHist}];return copy;},unlinkDoc:function(other){if(other instanceof CodeMirror)other=other.doc;if(this.linked)for(var i=0;i<this.linked.length;++i){var link=this.linked[i];if(link.doc!=other)continue;this.linked.splice(i,1);other.unlinkDoc(this);break;}
+if(other.history==this.history){var splitIds=[other.id];linkedDocs(other,function(doc){splitIds.push(doc.id);},true);other.history=makeHistory();other.history.done=copyHistoryArray(this.history.done,splitIds);other.history.undone=copyHistoryArray(this.history.undone,splitIds);}},iterLinkedDocs:function(f){linkedDocs(this,f);},getMode:function(){return this.mode;},getEditor:function(){return this.cm;}});Doc.prototype.eachLine=Doc.prototype.iter;var dontDelegate="iter insert remove copy getEditor".split(" ");for(var prop in Doc.prototype)if(Doc.prototype.hasOwnProperty(prop)&&indexOf(dontDelegate,prop)<0)
+CodeMirror.prototype[prop]=(function(method){return function(){return method.apply(this.doc,arguments);};})(Doc.prototype[prop]);eventMixin(Doc);function linkedDocs(doc,f,sharedHistOnly){function propagate(doc,skip,sharedHist){if(doc.linked)for(var i=0;i<doc.linked.length;++i){var rel=doc.linked[i];if(rel.doc==skip)continue;var shared=sharedHist&&rel.sharedHist;if(sharedHistOnly&&!shared)continue;f(rel.doc,shared);propagate(rel.doc,doc,shared);}}
+propagate(doc,null,true);}
+function attachDoc(cm,doc){if(doc.cm)throw new Error("This document is already in use.");cm.doc=doc;doc.cm=cm;estimateLineHeights(cm);loadMode(cm);if(!cm.options.lineWrapping)computeMaxLength(cm);cm.options.mode=doc.modeOption;regChange(cm);}
+function getLine(chunk,n){n-=chunk.first;while(!chunk.lines){for(var i=0;;++i){var child=chunk.children[i],sz=child.chunkSize();if(n<sz){chunk=child;break;}
+n-=sz;}}
+return chunk.lines[n];}
+function getBetween(doc,start,end){var out=[],n=start.line;doc.iter(start.line,end.line+1,function(line){var text=line.text;if(n==end.line)text=text.slice(0,end.ch);if(n==start.line)text=text.slice(start.ch);out.push(text);++n;});return out;}
+function getLines(doc,from,to){var out=[];doc.iter(from,to,function(line){out.push(line.text);});return out;}
+function updateLineHeight(line,height){var diff=height-line.height;for(var n=line;n;n=n.parent)n.height+=diff;}
+function lineNo(line){if(line.parent==null)return null;var cur=line.parent,no=indexOf(cur.lines,line);for(var chunk=cur.parent;chunk;cur=chunk,chunk=chunk.parent){for(var i=0;;++i){if(chunk.children[i]==cur)break;no+=chunk.children[i].chunkSize();}}
+return no+cur.first;}
+function lineAtHeight(chunk,h){var n=chunk.first;outer:do{for(var i=0,e=chunk.children.length;i<e;++i){var child=chunk.children[i],ch=child.height;if(h<ch){chunk=child;continue outer;}
+h-=ch;n+=child.chunkSize();}
+return n;}while(!chunk.lines);for(var i=0,e=chunk.lines.length;i<e;++i){var line=chunk.lines[i],lh=line.height;if(h<lh)break;h-=lh;}
+return n+i;}
+function heightAtLine(cm,lineObj){lineObj=visualLine(cm.doc,lineObj);var h=0,chunk=lineObj.parent;for(var i=0;i<chunk.lines.length;++i){var line=chunk.lines[i];if(line==lineObj)break;else h+=line.height;}
+for(var p=chunk.parent;p;chunk=p,p=chunk.parent){for(var i=0;i<p.children.length;++i){var cur=p.children[i];if(cur==chunk)break;else h+=cur.height;}}
+return h;}
+function getOrder(line){var order=line.order;if(order==null)order=line.order=bidiOrdering(line.text);return order;}
+function makeHistory(startGen){return{done:[],undone:[],undoDepth:Infinity,lastTime:0,lastOp:null,lastOrigin:null,generation:startGen||1,maxGeneration:startGen||1};}
+function attachLocalSpans(doc,change,from,to){var existing=change["spans_"+doc.id],n=0;doc.iter(Math.max(doc.first,from),Math.min(doc.first+doc.size,to),function(line){if(line.markedSpans)
+(existing||(existing=change["spans_"+doc.id]={}))[n]=line.markedSpans;++n;});}
+function historyChangeFromChange(doc,change){var from={line:change.from.line,ch:change.from.ch};var histChange={from:from,to:changeEnd(change),text:getBetween(doc,change.from,change.to)};attachLocalSpans(doc,histChange,change.from.line,change.to.line+1);linkedDocs(doc,function(doc){attachLocalSpans(doc,histChange,change.from.line,change.to.line+1);},true);return histChange;}
+function addToHistory(doc,change,selAfter,opId){var hist=doc.history;hist.undone.length=0;var time=+new Date,cur=lst(hist.done);if(cur&&(hist.lastOp==opId||hist.lastOrigin==change.origin&&change.origin&&((change.origin.charAt(0)=="+"&&doc.cm&&hist.lastTime>time-doc.cm.options.historyEventDelay)||change.origin.charAt(0)=="*"))){var last=lst(cur.changes);if(posEq(change.from,change.to)&&posEq(change.from,last.to)){last.to=changeEnd(change);}else{cur.changes.push(historyChangeFromChange(doc,change));}
+cur.anchorAfter=selAfter.anchor;cur.headAfter=selAfter.head;}else{cur={changes:[historyChangeFromChange(doc,change)],generation:hist.generation,anchorBefore:doc.sel.anchor,headBefore:doc.sel.head,anchorAfter:selAfter.anchor,headAfter:selAfter.head};hist.done.push(cur);hist.generation=++hist.maxGeneration;while(hist.done.length>hist.undoDepth)
+hist.done.shift();}
+hist.lastTime=time;hist.lastOp=opId;hist.lastOrigin=change.origin;}
+function removeClearedSpans(spans){if(!spans)return null;for(var i=0,out;i<spans.length;++i){if(spans[i].marker.explicitlyCleared){if(!out)out=spans.slice(0,i);}
+else if(out)out.push(spans[i]);}
+return!out?spans:out.length?out:null;}
+function getOldSpans(doc,change){var found=change["spans_"+doc.id];if(!found)return null;for(var i=0,nw=[];i<change.text.length;++i)
+nw.push(removeClearedSpans(found[i]));return nw;}
+function copyHistoryArray(events,newGroup){for(var i=0,copy=[];i<events.length;++i){var event=events[i],changes=event.changes,newChanges=[];copy.push({changes:newChanges,anchorBefore:event.anchorBefore,headBefore:event.headBefore,anchorAfter:event.anchorAfter,headAfter:event.headAfter});for(var j=0;j<changes.length;++j){var change=changes[j],m;newChanges.push({from:change.from,to:change.to,text:change.text});if(newGroup)for(var prop in change)if(m=prop.match(/^spans_(\d+)$/)){if(indexOf(newGroup,Number(m[1]))>-1){lst(newChanges)[prop]=change[prop];delete change[prop];}}}}
+return copy;}
+function rebaseHistSel(pos,from,to,diff){if(to<pos.line){pos.line+=diff;}else if(from<pos.line){pos.line=from;pos.ch=0;}}
+function rebaseHistArray(array,from,to,diff){for(var i=0;i<array.length;++i){var sub=array[i],ok=true;for(var j=0;j<sub.changes.length;++j){var cur=sub.changes[j];if(!sub.copied){cur.from=copyPos(cur.from);cur.to=copyPos(cur.to);}
+if(to<cur.from.line){cur.from.line+=diff;cur.to.line+=diff;}else if(from<=cur.to.line){ok=false;break;}}
+if(!sub.copied){sub.anchorBefore=copyPos(sub.anchorBefore);sub.headBefore=copyPos(sub.headBefore);sub.anchorAfter=copyPos(sub.anchorAfter);sub.readAfter=copyPos(sub.headAfter);sub.copied=true;}
+if(!ok){array.splice(0,i+1);i=0;}else{rebaseHistSel(sub.anchorBefore);rebaseHistSel(sub.headBefore);rebaseHistSel(sub.anchorAfter);rebaseHistSel(sub.headAfter);}}}
+function rebaseHist(hist,change){var from=change.from.line,to=change.to.line,diff=change.text.length-(to-from)-1;rebaseHistArray(hist.done,from,to,diff);rebaseHistArray(hist.undone,from,to,diff);}
+function stopMethod(){e_stop(this);}
+function addStop(event){if(!event.stop)event.stop=stopMethod;return event;}
+function e_preventDefault(e){if(e.preventDefault)e.preventDefault();else e.returnValue=false;}
+function e_stopPropagation(e){if(e.stopPropagation)e.stopPropagation();else e.cancelBubble=true;}
+function e_defaultPrevented(e){return e.defaultPrevented!=null?e.defaultPrevented:e.returnValue==false;}
+function e_stop(e){e_preventDefault(e);e_stopPropagation(e);}
+CodeMirror.e_stop=e_stop;CodeMirror.e_preventDefault=e_preventDefault;CodeMirror.e_stopPropagation=e_stopPropagation;function e_target(e){return e.target||e.srcElement;}
+function e_button(e){var b=e.which;if(b==null){if(e.button&1)b=1;else if(e.button&2)b=3;else if(e.button&4)b=2;}
+if(mac&&e.ctrlKey&&b==1)b=3;return b;}
+function on(emitter,type,f){if(emitter.addEventListener)
+emitter.addEventListener(type,f,false);else if(emitter.attachEvent)
+emitter.attachEvent("on"+type,f);else{var map=emitter._handlers||(emitter._handlers={});var arr=map[type]||(map[type]=[]);arr.push(f);}}
+function off(emitter,type,f){if(emitter.removeEventListener)
+emitter.removeEventListener(type,f,false);else if(emitter.detachEvent)
+emitter.detachEvent("on"+type,f);else{var arr=emitter._handlers&&emitter._handlers[type];if(!arr)return;for(var i=0;i<arr.length;++i)
+if(arr[i]==f){arr.splice(i,1);break;}}}
+function signal(emitter,type){var arr=emitter._handlers&&emitter._handlers[type];if(!arr)return;var args=Array.prototype.slice.call(arguments,2);for(var i=0;i<arr.length;++i)arr[i].apply(null,args);}
+var delayedCallbacks,delayedCallbackDepth=0;function signalLater(emitter,type){var arr=emitter._handlers&&emitter._handlers[type];if(!arr)return;var args=Array.prototype.slice.call(arguments,2);if(!delayedCallbacks){++delayedCallbackDepth;delayedCallbacks=[];setTimeout(fireDelayed,0);}
+function bnd(f){return function(){f.apply(null,args);};};for(var i=0;i<arr.length;++i)
+delayedCallbacks.push(bnd(arr[i]));}
+function signalDOMEvent(cm,e,override){signal(cm,override||e.type,cm,e);return e_defaultPrevented(e)||e.codemirrorIgnore;}
+function fireDelayed(){--delayedCallbackDepth;var delayed=delayedCallbacks;delayedCallbacks=null;for(var i=0;i<delayed.length;++i)delayed[i]();}
+function hasHandler(emitter,type){var arr=emitter._handlers&&emitter._handlers[type];return arr&&arr.length>0;}
+CodeMirror.on=on;CodeMirror.off=off;CodeMirror.signal=signal;function eventMixin(ctor){ctor.prototype.on=function(type,f){on(this,type,f);};ctor.prototype.off=function(type,f){off(this,type,f);};}
+var scrollerCutOff=30;var Pass=CodeMirror.Pass={toString:function(){return"CodeMirror.Pass";}};function Delayed(){this.id=null;}
+Delayed.prototype={set:function(ms,f){clearTimeout(this.id);this.id=setTimeout(f,ms);}};function countColumn(string,end,tabSize,startIndex,startValue){if(end==null){end=string.search(/[^\s\u00a0]/);if(end==-1)end=string.length;}
+for(var i=startIndex||0,n=startValue||0;i<end;++i){if(string.charAt(i)=="\t")n+=tabSize-(n%tabSize);else++n;}
+return n;}
+CodeMirror.countColumn=countColumn;var spaceStrs=[""];function spaceStr(n){while(spaceStrs.length<=n)
+spaceStrs.push(lst(spaceStrs)+" ");return spaceStrs[n];}
+function lst(arr){return arr[arr.length-1];}
+function selectInput(node){if(ios){node.selectionStart=0;node.selectionEnd=node.value.length;}else{try{node.select();}
+catch(_e){}}}
+function indexOf(collection,elt){if(collection.indexOf)return collection.indexOf(elt);for(var i=0,e=collection.length;i<e;++i)
+if(collection[i]==elt)return i;return-1;}
+function createObj(base,props){function Obj(){}
+Obj.prototype=base;var inst=new Obj();if(props)copyObj(props,inst);return inst;}
+function copyObj(obj,target){if(!target)target={};for(var prop in obj)if(obj.hasOwnProperty(prop))target[prop]=obj[prop];return target;}
+function emptyArray(size){for(var a=[],i=0;i<size;++i)a.push(undefined);return a;}
+function bind(f){var args=Array.prototype.slice.call(arguments,1);return function(){return f.apply(null,args);};}
+var nonASCIISingleCaseWordChar=/[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;function isWordChar(ch){return/\w/.test(ch)||ch>"\x80"&&(ch.toUpperCase()!=ch.toLowerCase()||nonASCIISingleCaseWordChar.test(ch));}
+function isEmpty(obj){for(var n in obj)if(obj.hasOwnProperty(n)&&obj[n])return false;return true;}
+var isExtendingChar=/[\u0300-\u036F\u0483-\u0487\u0488-\u0489\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\uA66F\uA670-\uA672\uA674-\uA67D\uA69F\udc00-\udfff]/;function elt(tag,content,className,style){var e=document.createElement(tag);if(className)e.className=className;if(style)e.style.cssText=style;if(typeof content=="string")setTextContent(e,content);else if(content)for(var i=0;i<content.length;++i)e.appendChild(content[i]);return e;}
+function removeChildren(e){for(var count=e.childNodes.length;count>0;--count)
+e.removeChild(e.firstChild);return e;}
+function removeChildrenAndAdd(parent,e){return removeChildren(parent).appendChild(e);}
+function setTextContent(e,str){if(ie_lt9){e.innerHTML="";e.appendChild(document.createTextNode(str));}else e.textContent=str;}
+function getRect(node){return node.getBoundingClientRect();}
+CodeMirror.replaceGetRect=function(f){getRect=f;};var dragAndDrop=function(){if(ie_lt9)return false;var div=elt('div');return"draggable"in div||"dragDrop"in div;}();function spanAffectsWrapping(){return false;}
+if(gecko)
+spanAffectsWrapping=function(str,i){return str.charCodeAt(i-1)==36&&str.charCodeAt(i)==39;};else if(safari&&!/Version\/([6-9]|\d\d)\b/.test(navigator.userAgent))
+spanAffectsWrapping=function(str,i){return/\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i-1,i+1));};else if(webkit&&!/Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
+spanAffectsWrapping=function(str,i){if(i>1&&str.charCodeAt(i-1)==45){if(/\w/.test(str.charAt(i-2))&&/[^\-?\.]/.test(str.charAt(i)))return true;if(i>2&&/[\d\.,]/.test(str.charAt(i-2))&&/[\d\.,]/.test(str.charAt(i)))return false;}
+return/[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|โ€ฆ[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i-1,i+1));};var knownScrollbarWidth;function scrollbarWidth(measure){if(knownScrollbarWidth!=null)return knownScrollbarWidth;var test=elt("div",null,null,"width: 50px; height: 50px; overflow-x: scroll");removeChildrenAndAdd(measure,test);if(test.offsetWidth)
+knownScrollbarWidth=test.offsetHeight-test.clientHeight;return knownScrollbarWidth||0;}
+var zwspSupported;function zeroWidthElement(measure){if(zwspSupported==null){var test=elt("span","\u200b");removeChildrenAndAdd(measure,elt("span",[test,document.createTextNode("x")]));if(measure.firstChild.offsetHeight!=0)
+zwspSupported=test.offsetWidth<=1&&test.offsetHeight>2&&!ie_lt8;}
+if(zwspSupported)return elt("span","\u200b");else return elt("span","\u00a0",null,"display: inline-block; width: 1px; margin-right: -1px");}
+var splitLines="\n\nb".split(/\n/).length!=3?function(string){var pos=0,result=[],l=string.length;while(pos<=l){var nl=string.indexOf("\n",pos);if(nl==-1)nl=string.length;var line=string.slice(pos,string.charAt(nl-1)=="\r"?nl-1:nl);var rt=line.indexOf("\r");if(rt!=-1){result.push(line.slice(0,rt));pos+=rt+1;}else{result.push(line);pos=nl+1;}}
+return result;}:function(string){return string.split(/\r\n?|\n/);};CodeMirror.splitLines=splitLines;var hasSelection=window.getSelection?function(te){try{return te.selectionStart!=te.selectionEnd;}
+catch(e){return false;}}:function(te){try{var range=te.ownerDocument.selection.createRange();}
+catch(e){}
+if(!range||range.parentElement()!=te)return false;return range.compareEndPoints("StartToEnd",range)!=0;};var hasCopyEvent=(function(){var e=elt("div");if("oncopy"in e)return true;e.setAttribute("oncopy","return;");return typeof e.oncopy=='function';})();var keyNames={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",91:"Mod",92:"Mod",93:"Mod",109:"-",107:"=",127:"Delete",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63276:"PageUp",63277:"PageDown",63275:"End",63273:"Home",63234:"Left",63232:"Up",63235:"Right",63233:"Down",63302:"Insert",63272:"Delete"};CodeMirror.keyNames=keyNames;(function(){for(var i=0;i<10;i++)keyNames[i+48]=String(i);for(var i=65;i<=90;i++)keyNames[i]=String.fromCharCode(i);for(var i=1;i<=12;i++)keyNames[i+111]=keyNames[i+63235]="F"+i;})();function iterateBidiSections(order,from,to,f){if(!order)return f(from,to,"ltr");var found=false;for(var i=0;i<order.length;++i){var part=order[i];if(part.from<to&&part.to>from||from==to&&part.to==from){f(Math.max(part.from,from),Math.min(part.to,to),part.level==1?"rtl":"ltr");found=true;}}
+if(!found)f(from,to,"ltr");}
+function bidiLeft(part){return part.level%2?part.to:part.from;}
+function bidiRight(part){return part.level%2?part.from:part.to;}
+function lineLeft(line){var order=getOrder(line);return order?bidiLeft(order[0]):0;}
+function lineRight(line){var order=getOrder(line);if(!order)return line.text.length;return bidiRight(lst(order));}
+function lineStart(cm,lineN){var line=getLine(cm.doc,lineN);var visual=visualLine(cm.doc,line);if(visual!=line)lineN=lineNo(visual);var order=getOrder(visual);var ch=!order?0:order[0].level%2?lineRight(visual):lineLeft(visual);return Pos(lineN,ch);}
+function lineEnd(cm,lineN){var merged,line;while(merged=collapsedSpanAtEnd(line=getLine(cm.doc,lineN)))
+lineN=merged.find().to.line;var order=getOrder(line);var ch=!order?line.text.length:order[0].level%2?lineLeft(line):lineRight(line);return Pos(lineN,ch);}
+function compareBidiLevel(order,a,b){var linedir=order[0].level;if(a==linedir)return true;if(b==linedir)return false;return a<b;}
+var bidiOther;function getBidiPartAt(order,pos){for(var i=0,found;i<order.length;++i){var cur=order[i];if(cur.from<pos&&cur.to>pos){bidiOther=null;return i;}
+if(cur.from==pos||cur.to==pos){if(found==null){found=i;}else if(compareBidiLevel(order,cur.level,order[found].level)){bidiOther=found;return i;}else{bidiOther=i;return found;}}}
+bidiOther=null;return found;}
+function moveInLine(line,pos,dir,byUnit){if(!byUnit)return pos+dir;do pos+=dir;while(pos>0&&isExtendingChar.test(line.text.charAt(pos)));return pos;}
+function moveVisually(line,start,dir,byUnit){var bidi=getOrder(line);if(!bidi)return moveLogically(line,start,dir,byUnit);var pos=getBidiPartAt(bidi,start),part=bidi[pos];var target=moveInLine(line,start,part.level%2?-dir:dir,byUnit);for(;;){if(target>part.from&&target<part.to)return target;if(target==part.from||target==part.to){if(getBidiPartAt(bidi,target)==pos)return target;part=bidi[pos+=dir];return(dir>0)==part.level%2?part.to:part.from;}else{part=bidi[pos+=dir];if(!part)return null;if((dir>0)==part.level%2)
+target=moveInLine(line,part.to,-1,byUnit);else
+target=moveInLine(line,part.from,1,byUnit);}}}
+function moveLogically(line,start,dir,byUnit){var target=start+dir;if(byUnit)while(target>0&&isExtendingChar.test(line.text.charAt(target)))target+=dir;return target<0||target>line.text.length?null:target;}
+var bidiOrdering=(function(){var lowTypes="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLL";var arabicTypes="rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmmrrrrrrrrrrrrrrrrrr";function charType(code){if(code<=0xff)return lowTypes.charAt(code);else if(0x590<=code&&code<=0x5f4)return"R";else if(0x600<=code&&code<=0x6ff)return arabicTypes.charAt(code-0x600);else if(0x700<=code&&code<=0x8ac)return"r";else return"L";}
+var bidiRE=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;var isNeutral=/[stwN]/,isStrong=/[LRr]/,countsAsLeft=/[Lb1n]/,countsAsNum=/[1n]/;var outerType="L";return function(str){if(!bidiRE.test(str))return false;var len=str.length,types=[];for(var i=0,type;i<len;++i)
+types.push(type=charType(str.charCodeAt(i)));for(var i=0,prev=outerType;i<len;++i){var type=types[i];if(type=="m")types[i]=prev;else prev=type;}
+for(var i=0,cur=outerType;i<len;++i){var type=types[i];if(type=="1"&&cur=="r")types[i]="n";else if(isStrong.test(type)){cur=type;if(type=="r")types[i]="R";}}
+for(var i=1,prev=types[0];i<len-1;++i){var type=types[i];if(type=="+"&&prev=="1"&&types[i+1]=="1")types[i]="1";else if(type==","&&prev==types[i+1]&&(prev=="1"||prev=="n"))types[i]=prev;prev=type;}
+for(var i=0;i<len;++i){var type=types[i];if(type==",")types[i]="N";else if(type=="%"){for(var end=i+1;end<len&&types[end]=="%";++end){}
+var replace=(i&&types[i-1]=="!")||(end<len-1&&types[end]=="1")?"1":"N";for(var j=i;j<end;++j)types[j]=replace;i=end-1;}}
+for(var i=0,cur=outerType;i<len;++i){var type=types[i];if(cur=="L"&&type=="1")types[i]="L";else if(isStrong.test(type))cur=type;}
+for(var i=0;i<len;++i){if(isNeutral.test(types[i])){for(var end=i+1;end<len&&isNeutral.test(types[end]);++end){}
+var before=(i?types[i-1]:outerType)=="L";var after=(end<len-1?types[end]:outerType)=="L";var replace=before||after?"L":"R";for(var j=i;j<end;++j)types[j]=replace;i=end-1;}}
+var order=[],m;for(var i=0;i<len;){if(countsAsLeft.test(types[i])){var start=i;for(++i;i<len&&countsAsLeft.test(types[i]);++i){}
+order.push({from:start,to:i,level:0});}else{var pos=i,at=order.length;for(++i;i<len&&types[i]!="L";++i){}
+for(var j=pos;j<i;){if(countsAsNum.test(types[j])){if(pos<j)order.splice(at,0,{from:pos,to:j,level:1});var nstart=j;for(++j;j<i&&countsAsNum.test(types[j]);++j){}
+order.splice(at,0,{from:nstart,to:j,level:2});pos=j;}else++j;}
+if(pos<i)order.splice(at,0,{from:pos,to:i,level:1});}}
+if(order[0].level==1&&(m=str.match(/^\s+/))){order[0].from=m[0].length;order.unshift({from:0,to:m[0].length,level:0});}
+if(lst(order).level==1&&(m=str.match(/\s+$/))){lst(order).to-=m[0].length;order.push({from:len-m[0].length,to:len,level:0});}
+if(order[0].level!=lst(order).level)
+order.push({from:len,to:len,level:order[0].level});return order;};})();CodeMirror.version="3.15.1";return CodeMirror;})();;CodeMirror.defineMode("css",function(config){return CodeMirror.getMode(config,"text/css");});CodeMirror.defineMode("css-base",function(config,parserConfig){"use strict";var indentUnit=config.indentUnit,hooks=parserConfig.hooks||{},atMediaTypes=parserConfig.atMediaTypes||{},atMediaFeatures=parserConfig.atMediaFeatures||{},propertyKeywords=parserConfig.propertyKeywords||{},colorKeywords=parserConfig.colorKeywords||{},valueKeywords=parserConfig.valueKeywords||{},allowNested=!!parserConfig.allowNested,type=null;function ret(style,tp){type=tp;return style;}
+function tokenBase(stream,state){var ch=stream.next();if(hooks[ch]){var result=hooks[ch](stream,state);if(result!==false)return result;}
+if(ch=="@"){stream.eatWhile(/[\w\\\-]/);return ret("def",stream.current());}
+else if(ch=="=")ret(null,"compare");else if((ch=="~"||ch=="|")&&stream.eat("="))return ret(null,"compare");else if(ch=="\""||ch=="'"){state.tokenize=tokenString(ch);return state.tokenize(stream,state);}
+else if(ch=="#"){stream.eatWhile(/[\w\\\-]/);return ret("atom","hash");}
+else if(ch=="!"){stream.match(/^\s*\w*/);return ret("keyword","important");}
+else if(/\d/.test(ch)){stream.eatWhile(/[\w.%]/);return ret("number","unit");}
+else if(ch==="-"){if(/\d/.test(stream.peek())){stream.eatWhile(/[\w.%]/);return ret("number","unit");}else if(stream.match(/^[^-]+-/)){return ret("meta","meta");}}
+else if(/[,+>*\/]/.test(ch)){return ret(null,"select-op");}
+else if(ch=="."&&stream.match(/^-?[_a-z][_a-z0-9-]*/i)){return ret("qualifier","qualifier");}
+else if(ch==":"){return ret("operator",ch);}
+else if(/[;{}\[\]\(\)]/.test(ch)){return ret(null,ch);}
+else if(ch=="u"&&stream.match("rl(")){stream.backUp(1);state.tokenize=tokenParenthesized;return ret("property","variable");}
+else{stream.eatWhile(/[\w\\\-]/);return ret("property","variable");}}
+function tokenString(quote,nonInclusive){return function(stream,state){var escaped=false,ch;while((ch=stream.next())!=null){if(ch==quote&&!escaped)
+break;escaped=!escaped&&ch=="\\";}
+if(!escaped){if(nonInclusive)stream.backUp(1);state.tokenize=tokenBase;}
+return ret("string","string");};}
+function tokenParenthesized(stream,state){stream.next();if(!stream.match(/\s*[\"\']/,false))
+state.tokenize=tokenString(")",true);else
+state.tokenize=tokenBase;return ret(null,"(");}
+return{startState:function(base){return{tokenize:tokenBase,baseIndent:base||0,stack:[],lastToken:null};},token:function(stream,state){state.tokenize=state.tokenize||tokenBase;if(state.tokenize==tokenBase&&stream.eatSpace())return null;var style=state.tokenize(stream,state);if(style&&typeof style!="string")style=ret(style[0],style[1]);var context=state.stack[state.stack.length-1];if(style=="variable"){if(type=="variable-definition")state.stack.push("propertyValue");return state.lastToken="variable-2";}else if(style=="property"){var word=stream.current().toLowerCase();if(context=="propertyValue"){if(valueKeywords.hasOwnProperty(word)){style="string-2";}else if(colorKeywords.hasOwnProperty(word)){style="keyword";}else{style="variable-2";}}else if(context=="rule"){if(!propertyKeywords.hasOwnProperty(word)){style+=" error";}}else if(context=="block"){if(propertyKeywords.hasOwnProperty(word)){style="property";}else if(colorKeywords.hasOwnProperty(word)){style="keyword";}else if(valueKeywords.hasOwnProperty(word)){style="string-2";}else{style="tag";}}else if(!context||context=="@media{"){style="tag";}else if(context=="@media"){if(atMediaTypes[stream.current()]){style="attribute";}else if(/^(only|not)$/.test(word)){style="keyword";}else if(word=="and"){style="error";}else if(atMediaFeatures.hasOwnProperty(word)){style="error";}else{style="attribute error";}}else if(context=="@mediaType"){if(atMediaTypes.hasOwnProperty(word)){style="attribute";}else if(word=="and"){style="operator";}else if(/^(only|not)$/.test(word)){style="error";}else{style="error";}}else if(context=="@mediaType("){if(propertyKeywords.hasOwnProperty(word)){}else if(atMediaTypes.hasOwnProperty(word)){style="error";}else if(word=="and"){style="operator";}else if(/^(only|not)$/.test(word)){style="error";}else{style+=" error";}}else if(context=="@import"){style="tag";}else{style="error";}}else if(style=="atom"){if(!context||context=="@media{"||context=="block"){style="builtin";}else if(context=="propertyValue"){if(!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())){style+=" error";}}else{style="error";}}else if(context=="@media"&&type=="{"){style="error";}
+if(type=="{"){if(context=="@media"||context=="@mediaType"){state.stack.pop();state.stack[state.stack.length-1]="@media{";}
+else{var newContext=allowNested?"block":"rule";state.stack.push(newContext);}}
+else if(type=="}"){var lastState=state.stack[state.stack.length-1];if(lastState=="interpolation")style="operator";state.stack.pop();if(context=="propertyValue")state.stack.pop();}
+else if(type=="interpolation")state.stack.push("interpolation");else if(type=="@media")state.stack.push("@media");else if(type=="@import")state.stack.push("@import");else if(context=="@media"&&/\b(keyword|attribute)\b/.test(style))
+state.stack.push("@mediaType");else if(context=="@mediaType"&&stream.current()==",")state.stack.pop();else if(context=="@mediaType"&&type=="(")state.stack.push("@mediaType(");else if(context=="@mediaType("&&type==")")state.stack.pop();else if(type==":"&&state.lastToken=="property")state.stack.push("propertyValue");else if(context=="propertyValue"&&type==";")state.stack.pop();else if(context=="@import"&&type==";")state.stack.pop();return state.lastToken=style;},indent:function(state,textAfter){var n=state.stack.length;if(/^\}/.test(textAfter))
+n-=state.stack[state.stack.length-1]=="propertyValue"?2:1;return state.baseIndent+n*indentUnit;},electricChars:"}",blockCommentStart:"/*",blockCommentEnd:"*/"};});(function(){function keySet(array){var keys={};for(var i=0;i<array.length;++i){keys[array[i]]=true;}
+return keys;}
+var atMediaTypes=keySet(["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"]);var atMediaFeatures=keySet(["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid"]);var propertyKeywords=keySet(["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid-cell","grid-column","grid-column-align","grid-column-sizing","grid-column-span","grid-columns","grid-flow","grid-row","grid-row-align","grid-row-sizing","grid-row-span","grid-rows","grid-template","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marker-offset","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","play-during","position","presentation-level","punctuation-trim","quotes","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-shadow","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-profile","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","kerning","text-anchor","writing-mode"]);var colorKeywords=keySet(["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"]);var valueKeywords=keySet(["above","absolute","activeborder","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","auto","avoid","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break-all","break-word","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","compact","condensed","contain","content","content-box","context-menu","continuous","copy","cover","crop","cross","crosshair","currentcolor","cursive","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ew-resize","expanded","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-table","inset","inside","intrinsic","invert","italic","justify","kannada","katakana","katakana-iroha","khmer","landscape","lao","large","larger","left","level","lighter","line-through","linear","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","overlay","overline","padding","padding-box","painted","paused","persian","plus-darker","plus-lighter","pointer","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radio","read-only","read-write","read-write-plaintext-only","relative","repeat","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","single","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","x-large","x-small","xor","xx-large","xx-small"]);function tokenCComment(stream,state){var maybeEnd=false,ch;while((ch=stream.next())!=null){if(maybeEnd&&ch=="/"){state.tokenize=null;break;}
+maybeEnd=(ch=="*");}
+return["comment","comment"];}
+CodeMirror.defineMIME("text/css",{atMediaTypes:atMediaTypes,atMediaFeatures:atMediaFeatures,propertyKeywords:propertyKeywords,colorKeywords:colorKeywords,valueKeywords:valueKeywords,hooks:{"<":function(stream,state){function tokenSGMLComment(stream,state){var dashes=0,ch;while((ch=stream.next())!=null){if(dashes>=2&&ch==">"){state.tokenize=null;break;}
+dashes=(ch=="-")?dashes+1:0;}
+return["comment","comment"];}
+if(stream.eat("!")){state.tokenize=tokenSGMLComment;return tokenSGMLComment(stream,state);}},"/":function(stream,state){if(stream.eat("*")){state.tokenize=tokenCComment;return tokenCComment(stream,state);}
+return false;}},name:"css-base"});CodeMirror.defineMIME("text/x-scss",{atMediaTypes:atMediaTypes,atMediaFeatures:atMediaFeatures,propertyKeywords:propertyKeywords,colorKeywords:colorKeywords,valueKeywords:valueKeywords,allowNested:true,hooks:{"$":function(stream){stream.match(/^[\w-]+/);if(stream.peek()==":"){return["variable","variable-definition"];}
+return["variable","variable"];},"/":function(stream,state){if(stream.eat("/")){stream.skipToEnd();return["comment","comment"];}else if(stream.eat("*")){state.tokenize=tokenCComment;return tokenCComment(stream,state);}else{return["operator","operator"];}},"#":function(stream){if(stream.eat("{")){return["operator","interpolation"];}else{stream.eatWhile(/[\w\\\-]/);return["atom","hash"];}}},name:"css-base"});})();;CodeMirror.defineMode("javascript",function(config,parserConfig){var indentUnit=config.indentUnit;var jsonMode=parserConfig.json;var isTS=parserConfig.typescript;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":kw("if"),"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,"this":kw("this")};if(isTS){var type={type:"variable",style:"variable-3"};var tsKeywords={"interface":kw("interface"),"class":kw("class"),"extends":kw("extends"),"constructor":kw("constructor"),"public":kw("public"),"private":kw("private"),"protected":kw("protected"),"static":kw("static"),"super":kw("super"),"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;}
+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]/);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");}
+var atomicTypes={"atom":true,"number":true,"variable":true,"string":true,"regexp":true,"this":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;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;}}}
+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){function inList(list){for(var v=list;v;v=v.next)
+if(v.name==varname)return true;return false;}
+var state=cx.state;if(state.context){cx.marked="def";if(inList(state.localVars))return;state.localVars={name:varname,next:state.localVars};}else{if(inList(state.globalVars))return;state.globalVars={name:varname,next:state.globalVars};}}
+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(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=="if")return cont(pushlex("form"),expression,statement,poplex,maybeelse(cx.state.indented));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){return expressionInner(type,maybeoperatorComma);}
+function expressionNoComma(type){return expressionInner(type,maybeoperatorNoComma);}
+function expressionInner(type,maybeop){if(atomicTypes.hasOwnProperty(type))return cont(maybeop);if(type=="function")return cont(functiondef);if(type=="keyword c")return cont(maybeexpression);if(type=="(")return cont(pushlex(")"),maybeexpression,expect(")"),poplex,maybeop);if(type=="operator")return cont(expression);if(type=="[")return cont(pushlex("]"),commasep(expressionNoComma,"]"),poplex,maybeop);if(type=="{")return cont(pushlex("}"),commasep(objprop,"}"),poplex,maybeop);return cont();}
+function maybeexpression(type){if(type.match(/[;\}\)\],]/))return pass();return pass(expression);}
+function maybeoperatorComma(type,value){if(type==",")return pass();return maybeoperatorNoComma(type,value,maybeoperatorComma);}
+function maybeoperatorNoComma(type,value,me){if(!me)me=maybeoperatorNoComma;if(type=="operator"){if(/\+\+|--/.test(value))return cont(me);if(value=="?")return cont(expression,expect(":"),expression);return cont(expression);}
+if(type==";")return;if(type=="(")return cont(pushlex(")","call"),commasep(expressionNoComma,")"),poplex,me);if(type==".")return cont(property,me);if(type=="[")return cont(pushlex("]"),expression,expect("]"),poplex,me);}
+function maybelabel(type){if(type==":")return cont(poplex,statement);return pass(maybeoperatorComma,expect(";"),poplex);}
+function property(type){if(type=="variable"){cx.marked="property";return cont();}}
+function objprop(type,value){if(type=="variable"){cx.marked="property";if(value=="get"||value=="set")return cont(getterSetter);}else if(type=="number"||type=="string"){cx.marked=type+" property";}
+if(atomicTypes.hasOwnProperty(type))return cont(expect(":"),expressionNoComma);}
+function getterSetter(type){if(type==":")return cont(expression);if(type!="variable")return cont(expect(":"),expression);cx.marked="property";return cont(functiondef);}
+function commasep(what,end){function proceed(type){if(type==","){var lex=cx.state.lexical;if(lex.info=="call")lex.pos=(lex.pos||0)+1;return cont(what,proceed);}
+if(type==end)return cont();return cont(expect(end));}
+return function(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(expressionNoComma,vardef2);if(type==",")return cont(vardef1);}
+function maybeelse(indent){return function(type,value){if(type=="keyword b"&&value=="else"){cx.state.lexical=new JSLexical(indent,0,"form",null,cx.state.lexical);return cont(statement,poplex);}
+return pass();};}
+function forspec1(type){if(type=="var")return cont(vardef1,expect(";"),forspec2);if(type==";")return cont(forspec2);if(type=="variable")return cont(formaybein);return pass(expression,expect(";"),forspec2);}
+function formaybein(_type,value){if(value=="in")return cont(expression);return cont(maybeoperatorComma,forspec2);}
+function forspec2(type,value){if(type==";")return cont(forspec3);if(value=="in")return cont(expression);return pass(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();}}
+return{startState:function(basecolumn){return{tokenize:jsTokenBase,lastType:null,cc:[],lexical:new JSLexical((basecolumn||0)-indentUnit,0,"block",false),localVars:parserConfig.localVars,globalVars:parserConfig.globalVars,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(state.tokenize!=jsTokenComment&&stream.eatSpace())return null;var style=state.tokenize(stream,state);if(type=="comment")return style;state.lastType=type=="operator"&&(content=="++"||content=="--")?"incdec":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(parserConfig.statementIndent!=null){if(type==")"&&lexical.prev&&lexical.prev.type=="stat")lexical=lexical.prev;if(lexical.type=="stat")return lexical.indented+parserConfig.statementIndent;}
+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:":{}",blockCommentStart:jsonMode?null:"/*",blockCommentEnd:jsonMode?null:"*/",lineComment:jsonMode?null:"//",jsonMode:jsonMode};});CodeMirror.defineMIME("text/javascript","javascript");CodeMirror.defineMIME("text/ecmascript","javascript");CodeMirror.defineMIME("application/javascript","javascript");CodeMirror.defineMIME("application/ecmascript","javascript");CodeMirror.defineMIME("application/json",{name:"javascript",json:true});CodeMirror.defineMIME("application/x-json",{name:"javascript",json:true});CodeMirror.defineMIME("text/typescript",{name:"javascript",typescript:true});CodeMirror.defineMIME("application/typescript",{name:"javascript",typescript:true});;CodeMirror.defineMode("xml",function(config,parserConfig){var indentUnit=config.indentUnit;var multilineTagIndentFactor=parserConfig.multilineTagIndentFactor||1;var multilineTagIndentPastTag=parserConfig.multilineTagIndentPastTag||true;var Kludges=parserConfig.htmlMode?{autoSelfClosers:{'area':true,'base':true,'br':true,'col':true,'command':true,'embed':true,'frame':true,'hr':true,'img':true,'input':true,'keygen':true,'link':true,'meta':true,'param':true,'source':true,'track':true,'wbr':true},implicitlyClosed:{'dd':true,'li':true,'optgroup':true,'option':true,'p':true,'rp':true,'rt':true,'tbody':true,'td':true,'tfoot':true,'th':true,'tr':true},contextGrabbers:{'dd':{'dd':true,'dt':true},'dt':{'dd':true,'dt':true},'li':{'li':true},'option':{'option':true,'optgroup':true},'optgroup':{'optgroup':true},'p':{'address':true,'article':true,'aside':true,'blockquote':true,'dir':true,'div':true,'dl':true,'fieldset':true,'footer':true,'form':true,'h1':true,'h2':true,'h3':true,'h4':true,'h5':true,'h6':true,'header':true,'hgroup':true,'hr':true,'menu':true,'nav':true,'ol':true,'p':true,'pre':true,'section':true,'table':true,'ul':true},'rp':{'rp':true,'rt':true},'rt':{'rp':true,'rt':true},'tbody':{'tbody':true,'tfoot':true},'td':{'td':true,'th':true},'tfoot':{'tbody':true},'th':{'td':true,'th':true},'thead':{'tbody':true,'tfoot':true},'tr':{'tr':true}},doNotIndent:{"pre":true},allowUnquoted:true,allowMissing:true}:{autoSelfClosers:{},implicitlyClosed:{},contextGrabbers:{},doNotIndent:{},allowUnquoted:false,allowMissing:false};var alignCDATA=parserConfig.alignCDATA;var tagName,type;function inText(stream,state){function chain(parser){state.tokenize=parser;return parser(stream,state);}
+var ch=stream.next();if(ch=="<"){if(stream.eat("!")){if(stream.eat("[")){if(stream.match("CDATA["))return chain(inBlock("atom","]]>"));else return null;}else if(stream.match("--")){return chain(inBlock("comment","-->"));}else if(stream.match("DOCTYPE",true,true)){stream.eatWhile(/[\w\._\-]/);return chain(doctype(1));}else{return null;}}else if(stream.eat("?")){stream.eatWhile(/[\w\._\-]/);state.tokenize=inBlock("meta","?>");return"meta";}else{var isClose=stream.eat("/");tagName="";var c;while((c=stream.eat(/[^\s\u00a0=<>\"\'\/?]/)))tagName+=c;if(!tagName)return"error";type=isClose?"closeTag":"openTag";state.tokenize=inTag;return"tag";}}else if(ch=="&"){var ok;if(stream.eat("#")){if(stream.eat("x")){ok=stream.eatWhile(/[a-fA-F\d]/)&&stream.eat(";");}else{ok=stream.eatWhile(/[\d]/)&&stream.eat(";");}}else{ok=stream.eatWhile(/[\w\.\-:]/)&&stream.eat(";");}
+return ok?"atom":"error";}else{stream.eatWhile(/[^&<]/);return null;}}
+function inTag(stream,state){var ch=stream.next();if(ch==">"||(ch=="/"&&stream.eat(">"))){state.tokenize=inText;type=ch==">"?"endTag":"selfcloseTag";return"tag";}else if(ch=="="){type="equals";return null;}else if(ch=="<"){return"error";}else if(/[\'\"]/.test(ch)){state.tokenize=inAttribute(ch);state.stringStartCol=stream.column();return state.tokenize(stream,state);}else{stream.eatWhile(/[^\s\u00a0=<>\"\']/);return"word";}}
+function inAttribute(quote){var closure=function(stream,state){while(!stream.eol()){if(stream.next()==quote){state.tokenize=inTag;break;}}
+return"string";};closure.isInAttribute=true;return closure;}
+function inBlock(style,terminator){return function(stream,state){while(!stream.eol()){if(stream.match(terminator)){state.tokenize=inText;break;}
+stream.next();}
+return style;};}
+function doctype(depth){return function(stream,state){var ch;while((ch=stream.next())!=null){if(ch=="<"){state.tokenize=doctype(depth+1);return state.tokenize(stream,state);}else if(ch==">"){if(depth==1){state.tokenize=inText;break;}else{state.tokenize=doctype(depth-1);return state.tokenize(stream,state);}}}
+return"meta";};}
+var curState,curStream,setStyle;function pass(){for(var i=arguments.length-1;i>=0;i--)curState.cc.push(arguments[i]);}
+function cont(){pass.apply(null,arguments);return true;}
+function pushContext(tagName,startOfLine){var noIndent=Kludges.doNotIndent.hasOwnProperty(tagName)||(curState.context&&curState.context.noIndent);curState.context={prev:curState.context,tagName:tagName,indent:curState.indented,startOfLine:startOfLine,noIndent:noIndent};}
+function popContext(){if(curState.context)curState.context=curState.context.prev;}
+function element(type){if(type=="openTag"){curState.tagName=tagName;curState.tagStart=curStream.column();return cont(attributes,endtag(curState.startOfLine));}else if(type=="closeTag"){var err=false;if(curState.context){if(curState.context.tagName!=tagName){if(Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())){popContext();}
+err=!curState.context||curState.context.tagName!=tagName;}}else{err=true;}
+if(err)setStyle="error";return cont(endclosetag(err));}
+return cont();}
+function endtag(startOfLine){return function(type){var tagName=curState.tagName;curState.tagName=curState.tagStart=null;if(type=="selfcloseTag"||(type=="endTag"&&Kludges.autoSelfClosers.hasOwnProperty(tagName.toLowerCase()))){maybePopContext(tagName.toLowerCase());return cont();}
+if(type=="endTag"){maybePopContext(tagName.toLowerCase());pushContext(tagName,startOfLine);return cont();}
+return cont();};}
+function endclosetag(err){return function(type){if(err)setStyle="error";if(type=="endTag"){popContext();return cont();}
+setStyle="error";return cont(arguments.callee);};}
+function maybePopContext(nextTagName){var parentTagName;while(true){if(!curState.context){return;}
+parentTagName=curState.context.tagName.toLowerCase();if(!Kludges.contextGrabbers.hasOwnProperty(parentTagName)||!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)){return;}
+popContext();}}
+function attributes(type){if(type=="word"){setStyle="attribute";return cont(attribute,attributes);}
+if(type=="endTag"||type=="selfcloseTag")return pass();setStyle="error";return cont(attributes);}
+function attribute(type){if(type=="equals")return cont(attvalue,attributes);if(!Kludges.allowMissing)setStyle="error";else if(type=="word"){setStyle="attribute";return cont(attribute,attributes);}
+return(type=="endTag"||type=="selfcloseTag")?pass():cont();}
+function attvalue(type){if(type=="string")return cont(attvaluemaybe);if(type=="word"&&Kludges.allowUnquoted){setStyle="string";return cont();}
+setStyle="error";return(type=="endTag"||type=="selfCloseTag")?pass():cont();}
+function attvaluemaybe(type){if(type=="string")return cont(attvaluemaybe);else return pass();}
+return{startState:function(){return{tokenize:inText,cc:[],indented:0,startOfLine:true,tagName:null,tagStart:null,context:null};},token:function(stream,state){if(!state.tagName&&stream.sol()){state.startOfLine=true;state.indented=stream.indentation();}
+if(stream.eatSpace())return null;setStyle=type=tagName=null;var style=state.tokenize(stream,state);state.type=type;if((style||type)&&style!="comment"){curState=state;curStream=stream;while(true){var comb=state.cc.pop()||element;if(comb(type||style))break;}}
+state.startOfLine=false;return setStyle||style;},indent:function(state,textAfter,fullLine){var context=state.context;if(state.tokenize.isInAttribute){return state.stringStartCol+1;}
+if((state.tokenize!=inTag&&state.tokenize!=inText)||context&&context.noIndent)
+return fullLine?fullLine.match(/^(\s*)/)[0].length:0;if(state.tagName){if(multilineTagIndentPastTag)
+return state.tagStart+state.tagName.length+2;else
+return state.tagStart+indentUnit*multilineTagIndentFactor;}
+if(alignCDATA&&/<!\[CDATA\[/.test(textAfter))return 0;if(context&&/^<\//.test(textAfter))
+context=context.prev;while(context&&!context.startOfLine)
+context=context.prev;if(context)return context.indent+indentUnit;else return 0;},electricChars:"/",blockCommentStart:"<!--",blockCommentEnd:"-->",configuration:parserConfig.htmlMode?"html":"xml",helperType:parserConfig.htmlMode?"html":"xml"};});CodeMirror.defineMIME("text/xml","xml");CodeMirror.defineMIME("application/xml","xml");if(!CodeMirror.mimeModes.hasOwnProperty("text/html"))
+CodeMirror.defineMIME("text/html",{name:"xml",htmlMode:true});;CodeMirror.defineMode("htmlmixed",function(config,parserConfig){var htmlMode=CodeMirror.getMode(config,{name:"xml",htmlMode:true});var cssMode=CodeMirror.getMode(config,"css");var scriptTypes=[],scriptTypesConf=parserConfig&&parserConfig.scriptTypes;scriptTypes.push({matches:/^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,mode:CodeMirror.getMode(config,"javascript")});if(scriptTypesConf)for(var i=0;i<scriptTypesConf.length;++i){var conf=scriptTypesConf[i];scriptTypes.push({matches:conf.matches,mode:conf.mode&&CodeMirror.getMode(config,conf.mode)});}
+scriptTypes.push({matches:/./,mode:CodeMirror.getMode(config,"text/plain")});function html(stream,state){var tagName=state.htmlState.tagName;var style=htmlMode.token(stream,state.htmlState);if(tagName=="script"&&/\btag\b/.test(style)&&stream.current()==">"){var scriptType=stream.string.slice(Math.max(0,stream.pos-100),stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);scriptType=scriptType?scriptType[1]:"";if(scriptType&&/[\"\']/.test(scriptType.charAt(0)))scriptType=scriptType.slice(1,scriptType.length-1);for(var i=0;i<scriptTypes.length;++i){var tp=scriptTypes[i];if(typeof tp.matches=="string"?scriptType==tp.matches:tp.matches.test(scriptType)){if(tp.mode){state.token=script;state.localMode=tp.mode;state.localState=tp.mode.startState&&tp.mode.startState(htmlMode.indent(state.htmlState,""));}
+break;}}}else if(tagName=="style"&&/\btag\b/.test(style)&&stream.current()==">"){state.token=css;state.localMode=cssMode;state.localState=cssMode.startState(htmlMode.indent(state.htmlState,""));}
+return style;}
+function maybeBackup(stream,pat,style){var cur=stream.current();var close=cur.search(pat),m;if(close>-1)stream.backUp(cur.length-close);else if(m=cur.match(/<\/?$/)){stream.backUp(cur.length);if(!stream.match(pat,false))stream.match(cur[0]);}
+return style;}
+function script(stream,state){if(stream.match(/^<\/\s*script\s*>/i,false)){state.token=html;state.localState=state.localMode=null;return html(stream,state);}
+return maybeBackup(stream,/<\/\s*script\s*>/,state.localMode.token(stream,state.localState));}
+function css(stream,state){if(stream.match(/^<\/\s*style\s*>/i,false)){state.token=html;state.localState=state.localMode=null;return html(stream,state);}
+return maybeBackup(stream,/<\/\s*style\s*>/,cssMode.token(stream,state.localState));}
+return{startState:function(){var state=htmlMode.startState();return{token:html,localMode:null,localState:null,htmlState:state};},copyState:function(state){if(state.localState)
+var local=CodeMirror.copyState(state.localMode,state.localState);return{token:state.token,localMode:state.localMode,localState:local,htmlState:CodeMirror.copyState(htmlMode,state.htmlState)};},token:function(stream,state){return state.token(stream,state);},indent:function(state,textAfter){if(!state.localMode||/^\s*<\//.test(textAfter))
+return htmlMode.indent(state.htmlState,textAfter);else if(state.localMode.indent)
+return state.localMode.indent(state.localState,textAfter);else
+return CodeMirror.Pass;},electricChars:"/{}:",innerMode:function(state){return{state:state.localState||state.htmlState,mode:state.localMode||htmlMode};}};},"xml","javascript","css");CodeMirror.defineMIME("text/html","htmlmixed");;(function(){var ie_lt8=/MSIE \d/.test(navigator.userAgent)&&(document.documentMode==null||document.documentMode<8);var Pos=CodeMirror.Pos;var matching={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"};function findMatchingBracket(cm,where,strict){var state=cm.state.matchBrackets;var maxScanLen=(state&&state.maxScanLineLength)||10000;var cur=where||cm.getCursor(),line=cm.getLineHandle(cur.line),pos=cur.ch-1;var match=(pos>=0&&matching[line.text.charAt(pos)])||matching[line.text.charAt(++pos)];if(!match)return null;var forward=match.charAt(1)==">",d=forward?1:-1;if(strict&&forward!=(pos==cur.ch))return null;var style=cm.getTokenTypeAt(Pos(cur.line,pos+1));var stack=[line.text.charAt(pos)],re=/[(){}[\]]/;function scan(line,lineNo,start){if(!line.text)return;var pos=forward?0:line.text.length-1,end=forward?line.text.length:-1;if(line.text.length>maxScanLen)return null;if(start!=null)pos=start+d;for(;pos!=end;pos+=d){var ch=line.text.charAt(pos);if(re.test(ch)&&cm.getTokenTypeAt(Pos(lineNo,pos+1))==style){var match=matching[ch];if(match.charAt(1)==">"==forward)stack.push(ch);else if(stack.pop()!=match.charAt(0))return{pos:pos,match:false};else if(!stack.length)return{pos:pos,match:true};}}}
+for(var i=cur.line,found,e=forward?Math.min(i+100,cm.lineCount()):Math.max(-1,i-100);i!=e;i+=d){if(i==cur.line)found=scan(line,i,pos);else found=scan(cm.getLineHandle(i),i);if(found)break;}
+return{from:Pos(cur.line,pos),to:found&&Pos(i,found.pos),match:found&&found.match,forward:forward};}
+function matchBrackets(cm,autoclear){var maxHighlightLen=cm.state.matchBrackets.maxHighlightLineLength||1000;var found=findMatchingBracket(cm);if(!found||cm.getLine(found.from.line).length>maxHighlightLen||found.to&&cm.getLine(found.to.line).length>maxHighlightLen)
+return;var style=found.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket";var one=cm.markText(found.from,Pos(found.from.line,found.from.ch+1),{className:style});var two=found.to&&cm.markText(found.to,Pos(found.to.line,found.to.ch+1),{className:style});if(ie_lt8&&cm.state.focused)cm.display.input.focus();var clear=function(){cm.operation(function(){one.clear();two&&two.clear();});};if(autoclear)setTimeout(clear,800);else return clear;}
+var currentlyHighlighted=null;function doMatchBrackets(cm){cm.operation(function(){if(currentlyHighlighted){currentlyHighlighted();currentlyHighlighted=null;}
+if(!cm.somethingSelected())currentlyHighlighted=matchBrackets(cm,false);});}
+CodeMirror.defineOption("matchBrackets",false,function(cm,val,old){if(old&&old!=CodeMirror.Init)
+cm.off("cursorActivity",doMatchBrackets);if(val){cm.state.matchBrackets=typeof val=="object"?val:{};cm.on("cursorActivity",doMatchBrackets);}});CodeMirror.defineExtension("matchBrackets",function(){matchBrackets(this,true);});CodeMirror.defineExtension("findMatchingBracket",function(pos,strict){return findMatchingBracket(this,pos,strict);});})();;(function(){var DEFAULT_BRACKETS="()[]{}''\"\"";var DEFAULT_EXPLODE_ON_ENTER="[]{}";var SPACE_CHAR_REGEX=/\s/;CodeMirror.defineOption("autoCloseBrackets",false,function(cm,val,old){if(old!=CodeMirror.Init&&old)
+cm.removeKeyMap("autoCloseBrackets");if(!val)return;var pairs=DEFAULT_BRACKETS,explode=DEFAULT_EXPLODE_ON_ENTER;if(typeof val=="string")pairs=val;else if(typeof val=="object"){if(val.pairs!=null)pairs=val.pairs;if(val.explode!=null)explode=val.explode;}
+var map=buildKeymap(pairs);if(explode)map.Enter=buildExplodeHandler(explode);cm.addKeyMap(map);});function charsAround(cm,pos){var str=cm.getRange(CodeMirror.Pos(pos.line,pos.ch-1),CodeMirror.Pos(pos.line,pos.ch+1));return str.length==2?str:null;}
+function buildKeymap(pairs){var map={name:"autoCloseBrackets",Backspace:function(cm){if(cm.somethingSelected())return CodeMirror.Pass;var cur=cm.getCursor(),around=charsAround(cm,cur);if(around&&pairs.indexOf(around)%2==0)
+cm.replaceRange("",CodeMirror.Pos(cur.line,cur.ch-1),CodeMirror.Pos(cur.line,cur.ch+1));else
+return CodeMirror.Pass;}};var closingBrackets="";for(var i=0;i<pairs.length;i+=2)(function(left,right){if(left!=right)closingBrackets+=right;function surround(cm){var selection=cm.getSelection();cm.replaceSelection(left+selection+right);}
+function maybeOverwrite(cm){var cur=cm.getCursor(),ahead=cm.getRange(cur,CodeMirror.Pos(cur.line,cur.ch+1));if(ahead!=right||cm.somethingSelected())return CodeMirror.Pass;else cm.execCommand("goCharRight");}
+map["'"+left+"'"]=function(cm){if(left=="'"&&cm.getTokenAt(cm.getCursor()).type=="comment")
+return CodeMirror.Pass;if(cm.somethingSelected())return surround(cm);if(left==right&&maybeOverwrite(cm)!=CodeMirror.Pass)return;var cur=cm.getCursor(),ahead=CodeMirror.Pos(cur.line,cur.ch+1);var line=cm.getLine(cur.line),nextChar=line.charAt(cur.ch),curChar=cur.ch>0?line.charAt(cur.ch-1):"";if(left==right&&CodeMirror.isWordChar(curChar))
+return CodeMirror.Pass;if(line.length==cur.ch||closingBrackets.indexOf(nextChar)>=0||SPACE_CHAR_REGEX.test(nextChar))
+cm.replaceSelection(left+right,{head:ahead,anchor:ahead});else
+return CodeMirror.Pass;};if(left!=right)map["'"+right+"'"]=maybeOverwrite;})(pairs.charAt(i),pairs.charAt(i+1));return map;}
+function buildExplodeHandler(pairs){return function(cm){var cur=cm.getCursor(),around=charsAround(cm,cur);if(!around||pairs.indexOf(around)%2!=0)return CodeMirror.Pass;cm.operation(function(){var newPos=CodeMirror.Pos(cur.line+1,0);cm.replaceSelection("\n\n",{anchor:newPos,head:newPos},"+input");cm.indentLine(cur.line+1,null,true);cm.indentLine(cur.line+2,null,true);});};}})();;(function(){"use strict";CodeMirror.defineOption("styleSelectedText",false,function(cm,val,old){var prev=old&&old!=CodeMirror.Init;if(val&&!prev){cm.state.markedSelection=[];cm.state.markedSelectionStyle=typeof val=="string"?val:"CodeMirror-selectedtext";reset(cm);cm.on("cursorActivity",onCursorActivity);cm.on("change",onChange);}else if(!val&&prev){cm.off("cursorActivity",onCursorActivity);cm.off("change",onChange);clear(cm);cm.state.markedSelection=cm.state.markedSelectionStyle=null;}});function onCursorActivity(cm){cm.operation(function(){update(cm);});}
+function onChange(cm){if(cm.state.markedSelection.length)
+cm.operation(function(){clear(cm);});}
+var CHUNK_SIZE=8;var Pos=CodeMirror.Pos;function cmp(pos1,pos2){return pos1.line-pos2.line||pos1.ch-pos2.ch;}
+function coverRange(cm,from,to,addAt){if(cmp(from,to)==0)return;var array=cm.state.markedSelection;var cls=cm.state.markedSelectionStyle;for(var line=from.line;;){var start=line==from.line?from:Pos(line,0);var endLine=line+CHUNK_SIZE,atEnd=endLine>=to.line;var end=atEnd?to:Pos(endLine,0);var mark=cm.markText(start,end,{className:cls});if(addAt==null)array.push(mark);else array.splice(addAt++,0,mark);if(atEnd)break;line=endLine;}}
+function clear(cm){var array=cm.state.markedSelection;for(var i=0;i<array.length;++i)array[i].clear();array.length=0;}
+function reset(cm){clear(cm);var from=cm.getCursor("start"),to=cm.getCursor("end");coverRange(cm,from,to);}
+function update(cm){var from=cm.getCursor("start"),to=cm.getCursor("end");if(cmp(from,to)==0)return clear(cm);var array=cm.state.markedSelection;if(!array.length)return coverRange(cm,from,to);var coverStart=array[0].find(),coverEnd=array[array.length-1].find();if(!coverStart||!coverEnd||to.line-from.line<CHUNK_SIZE||cmp(from,coverEnd.to)>=0||cmp(to,coverStart.from)<=0)
+return reset(cm);while(cmp(from,coverStart.from)>0){array.shift().clear();coverStart=array[0].find();}
+if(cmp(from,coverStart.from)<0){if(coverStart.to.line-from.line<CHUNK_SIZE){array.shift().clear();coverRange(cm,from,coverStart.to,0);}else{coverRange(cm,from,coverStart.from,0);}}
+while(cmp(to,coverEnd.to)<0){array.pop().clear();coverEnd=array[array.length-1].find();}
+if(cmp(to,coverEnd.to)>0){if(to.line-coverEnd.from.line<CHUNK_SIZE){array.pop().clear();coverRange(cm,coverEnd.from,to);}else{coverRange(cm,coverEnd.to,to);}}}})();;(function(){"use strict";var noOptions={};var nonWS=/[^\s\u00a0]/;var Pos=CodeMirror.Pos;function firstNonWS(str){var found=str.search(nonWS);return found==-1?0:found;}
+CodeMirror.commands.toggleComment=function(cm){var from=cm.getCursor("start"),to=cm.getCursor("end");cm.uncomment(from,to)||cm.lineComment(from,to);};CodeMirror.defineExtension("lineComment",function(from,to,options){if(!options)options=noOptions;var self=this,mode=CodeMirror.innerMode(self.getMode(),self.getTokenAt(from).state).mode;var commentString=options.lineComment||mode.lineComment;if(!commentString){if(options.blockCommentStart||mode.blockCommentStart){options.fullLines=true;self.blockComment(from,to,options);}
+return;}
+var firstLine=self.getLine(from.line);if(firstLine==null)return;var end=Math.min(to.ch!=0||to.line==from.line?to.line+1:to.line,self.lastLine()+1);var pad=options.padding==null?" ":options.padding;var blankLines=options.commentBlankLines;self.operation(function(){if(options.indent){var baseString=firstLine.slice(0,firstNonWS(firstLine));for(var i=from.line;i<end;++i){var line=self.getLine(i),cut=baseString.length;if(!blankLines&&!nonWS.test(line))continue;if(line.slice(0,cut)!=baseString)cut=firstNonWS(line);self.replaceRange(baseString+commentString+pad,Pos(i,0),Pos(i,cut));}}else{for(var i=from.line;i<end;++i){if(blankLines||nonWS.test(self.getLine(i)))
+self.replaceRange(commentString+pad,Pos(i,0));}}});});CodeMirror.defineExtension("blockComment",function(from,to,options){if(!options)options=noOptions;var self=this,mode=CodeMirror.innerMode(self.getMode(),self.getTokenAt(from).state).mode;var startString=options.blockCommentStart||mode.blockCommentStart;var endString=options.blockCommentEnd||mode.blockCommentEnd;if(!startString||!endString){if((options.lineComment||mode.lineComment)&&options.fullLines!=false)
+self.lineComment(from,to,options);return;}
+var end=Math.min(to.line,self.lastLine());if(end!=from.line&&to.ch==0&&nonWS.test(self.getLine(end)))--end;var pad=options.padding==null?" ":options.padding;if(from.line>end)return;self.operation(function(){if(options.fullLines!=false){var lastLineHasText=nonWS.test(self.getLine(end));self.replaceRange(pad+endString,Pos(end));self.replaceRange(startString+pad,Pos(from.line,0));var lead=options.blockCommentLead||mode.blockCommentLead;if(lead!=null)for(var i=from.line+1;i<=end;++i)
+if(i!=end||lastLineHasText)
+self.replaceRange(lead+pad,Pos(i,0));}else{self.replaceRange(endString,to);self.replaceRange(startString,from);}});});CodeMirror.defineExtension("uncomment",function(from,to,options){if(!options)options=noOptions;var self=this,mode=CodeMirror.innerMode(self.getMode(),self.getTokenAt(from).state).mode;var end=Math.min(to.line,self.lastLine()),start=Math.min(from.line,end);var lineString=options.lineComment||mode.lineComment,lines=[];var pad=options.padding==null?" ":options.padding;lineComment:for(;;){if(!lineString)break;for(var i=start;i<=end;++i){var line=self.getLine(i);var found=line.indexOf(lineString);if(found==-1&&(i!=end||i==start)&&nonWS.test(line))break lineComment;if(i!=start&&found>-1&&nonWS.test(line.slice(0,found)))break lineComment;lines.push(line);}
+self.operation(function(){for(var i=start;i<=end;++i){var line=lines[i-start];var pos=line.indexOf(lineString),endPos=pos+lineString.length;if(pos<0)continue;if(line.slice(endPos,endPos+pad.length)==pad)endPos+=pad.length;self.replaceRange("",Pos(i,pos),Pos(i,endPos));}});return true;}
+var startString=options.blockCommentStart||mode.blockCommentStart;var endString=options.blockCommentEnd||mode.blockCommentEnd;if(!startString||!endString)return false;var lead=options.blockCommentLead||mode.blockCommentLead;var startLine=self.getLine(start),endLine=end==start?startLine:self.getLine(end);var open=startLine.indexOf(startString),close=endLine.lastIndexOf(endString);if(close==-1&&start!=end){endLine=self.getLine(--end);close=endLine.lastIndexOf(endString);}
+if(open==-1||close==-1)return false;self.operation(function(){self.replaceRange("",Pos(end,close-(pad&&endLine.slice(close-pad.length,close)==pad?pad.length:0)),Pos(end,close+endString.length));var openEnd=open+startString.length;if(pad&&startLine.slice(openEnd,openEnd+pad.length)==pad)openEnd+=pad.length;self.replaceRange("",Pos(start,open),Pos(start,openEnd));if(lead)for(var i=start+1;i<=end;++i){var line=self.getLine(i),found=line.indexOf(lead);if(found==-1||nonWS.test(line.slice(0,found)))continue;var foundEnd=found+lead.length;if(pad&&line.slice(foundEnd,foundEnd+pad.length)==pad)foundEnd+=pad.length;self.replaceRange("",Pos(i,found),Pos(i,foundEnd));}});return true;});})();;CodeMirror.overlayMode=CodeMirror.overlayParser=function(base,overlay,combine){return{startState:function(){return{base:CodeMirror.startState(base),overlay:CodeMirror.startState(overlay),basePos:0,baseCur:null,overlayPos:0,overlayCur:null};},copyState:function(state){return{base:CodeMirror.copyState(base,state.base),overlay:CodeMirror.copyState(overlay,state.overlay),basePos:state.basePos,baseCur:null,overlayPos:state.overlayPos,overlayCur:null};},token:function(stream,state){if(stream.start==state.basePos){state.baseCur=base.token(stream,state.base);state.basePos=stream.pos;}
+if(stream.start==state.overlayPos){stream.pos=stream.start;state.overlayCur=overlay.token(stream,state.overlay);state.overlayPos=stream.pos;}
+stream.pos=Math.min(state.basePos,state.overlayPos);if(stream.eol())state.basePos=state.overlayPos=0;if(state.overlayCur==null)return state.baseCur;if(state.baseCur!=null&&combine)return state.baseCur+" "+state.overlayCur;else return state.overlayCur;},indent:base.indent&&function(state,textAfter){return base.indent(state.base,textAfter);},electricChars:base.electricChars,innerMode:function(state){return{state:state.base,mode:base};},blankLine:function(state){if(base.blankLine)base.blankLine(state.base);if(overlay.blankLine)overlay.blankLine(state.overlay);}};};;CodeMirror.defineMode("htmlembedded",function(config,parserConfig){var scriptStartRegex=parserConfig.scriptStartRegex||/^<%/i,scriptEndRegex=parserConfig.scriptEndRegex||/^%>/i;var scriptingMode,htmlMixedMode;function htmlDispatch(stream,state){if(stream.match(scriptStartRegex,false)){state.token=scriptingDispatch;return scriptingMode.token(stream,state.scriptState);}
+else
+return htmlMixedMode.token(stream,state.htmlState);}
+function scriptingDispatch(stream,state){if(stream.match(scriptEndRegex,false)){state.token=htmlDispatch;return htmlMixedMode.token(stream,state.htmlState);}
+else
+return scriptingMode.token(stream,state.scriptState);}
+return{startState:function(){scriptingMode=scriptingMode||CodeMirror.getMode(config,parserConfig.scriptingModeSpec);htmlMixedMode=htmlMixedMode||CodeMirror.getMode(config,"htmlmixed");return{token:parserConfig.startOpen?scriptingDispatch:htmlDispatch,htmlState:CodeMirror.startState(htmlMixedMode),scriptState:CodeMirror.startState(scriptingMode)};},token:function(stream,state){return state.token(stream,state);},indent:function(state,textAfter){if(state.token==htmlDispatch)
+return htmlMixedMode.indent(state.htmlState,textAfter);else if(scriptingMode.indent)
+return scriptingMode.indent(state.scriptState,textAfter);},copyState:function(state){return{token:state.token,htmlState:CodeMirror.copyState(htmlMixedMode,state.htmlState),scriptState:CodeMirror.copyState(scriptingMode,state.scriptState)};},electricChars:"/{}:",innerMode:function(state){if(state.token==scriptingDispatch)return{state:state.scriptState,mode:scriptingMode};else return{state:state.htmlState,mode:htmlMixedMode};}};},"htmlmixed");CodeMirror.defineMIME("application/x-ejs",{name:"htmlembedded",scriptingModeSpec:"javascript"});CodeMirror.defineMIME("application/x-aspx",{name:"htmlembedded",scriptingModeSpec:"text/x-csharp"});CodeMirror.defineMIME("application/x-jsp",{name:"htmlembedded",scriptingModeSpec:"text/x-java"});CodeMirror.defineMIME("application/x-erb",{name:"htmlembedded",scriptingModeSpec:"ruby"});;CodeMirror.defineMode("clike",function(config,parserConfig){var indentUnit=config.indentUnit,statementIndentUnit=parserConfig.statementIndentUnit||indentUnit,dontAlignCalls=parserConfig.dontAlignCalls,keywords=parserConfig.keywords||{},builtin=parserConfig.builtin||{},blockKeywords=parserConfig.blockKeywords||{},atoms=parserConfig.atoms||{},hooks=parserConfig.hooks||{},multiLineStrings=parserConfig.multiLineStrings;var isOperatorChar=/[+\-*&%=<>!?|\/]/;var curPunc;function tokenBase(stream,state){var ch=stream.next();if(hooks[ch]){var result=hooks[ch](stream,state);if(result!==false)return result;}
+if(ch=='"'||ch=="'"){state.tokenize=tokenString(ch);return state.tokenize(stream,state);}
+if(/[\[\]{}\(\),;\:\.]/.test(ch)){curPunc=ch;return null;}
+if(/\d/.test(ch)){stream.eatWhile(/[\w\.]/);return"number";}
+if(ch=="/"){if(stream.eat("*")){state.tokenize=tokenComment;return tokenComment(stream,state);}
+if(stream.eat("/")){stream.skipToEnd();return"comment";}}
+if(isOperatorChar.test(ch)){stream.eatWhile(isOperatorChar);return"operator";}
+stream.eatWhile(/[\w\$_]/);var cur=stream.current();if(keywords.propertyIsEnumerable(cur)){if(blockKeywords.propertyIsEnumerable(cur))curPunc="newstatement";return"keyword";}
+if(builtin.propertyIsEnumerable(cur)){if(blockKeywords.propertyIsEnumerable(cur))curPunc="newstatement";return"builtin";}
+if(atoms.propertyIsEnumerable(cur))return"atom";return"variable";}
+function tokenString(quote){return function(stream,state){var escaped=false,next,end=false;while((next=stream.next())!=null){if(next==quote&&!escaped){end=true;break;}
+escaped=!escaped&&next=="\\";}
+if(end||!(escaped||multiLineStrings))
+state.tokenize=null;return"string";};}
+function tokenComment(stream,state){var maybeEnd=false,ch;while(ch=stream.next()){if(ch=="/"&&maybeEnd){state.tokenize=null;break;}
+maybeEnd=(ch=="*");}
+return"comment";}
+function Context(indented,column,type,align,prev){this.indented=indented;this.column=column;this.type=type;this.align=align;this.prev=prev;}
+function pushContext(state,col,type){var indent=state.indented;if(state.context&&state.context.type=="statement")
+indent=state.context.indented;return state.context=new Context(indent,col,type,null,state.context);}
+function popContext(state){var t=state.context.type;if(t==")"||t=="]"||t=="}")
+state.indented=state.context.indented;return state.context=state.context.prev;}
+return{startState:function(basecolumn){return{tokenize:null,context:new Context((basecolumn||0)-indentUnit,0,"top",false),indented:0,startOfLine:true};},token:function(stream,state){var ctx=state.context;if(stream.sol()){if(ctx.align==null)ctx.align=false;state.indented=stream.indentation();state.startOfLine=true;}
+if(stream.eatSpace())return null;curPunc=null;var style=(state.tokenize||tokenBase)(stream,state);if(style=="comment"||style=="meta")return style;if(ctx.align==null)ctx.align=true;if((curPunc==";"||curPunc==":"||curPunc==",")&&ctx.type=="statement")popContext(state);else if(curPunc=="{")pushContext(state,stream.column(),"}");else if(curPunc=="[")pushContext(state,stream.column(),"]");else if(curPunc=="(")pushContext(state,stream.column(),")");else if(curPunc=="}"){while(ctx.type=="statement")ctx=popContext(state);if(ctx.type=="}")ctx=popContext(state);while(ctx.type=="statement")ctx=popContext(state);}
+else if(curPunc==ctx.type)popContext(state);else if(((ctx.type=="}"||ctx.type=="top")&&curPunc!=';')||(ctx.type=="statement"&&curPunc=="newstatement"))
+pushContext(state,stream.column(),"statement");state.startOfLine=false;return style;},indent:function(state,textAfter){if(state.tokenize!=tokenBase&&state.tokenize!=null)return CodeMirror.Pass;var ctx=state.context,firstChar=textAfter&&textAfter.charAt(0);if(ctx.type=="statement"&&firstChar=="}")ctx=ctx.prev;var closing=firstChar==ctx.type;if(ctx.type=="statement")return ctx.indented+(firstChar=="{"?0:statementIndentUnit);else if(ctx.align&&(!dontAlignCalls||ctx.type!=")"))return ctx.column+(closing?0:1);else if(ctx.type==")"&&!closing)return ctx.indented+statementIndentUnit;else return ctx.indented+(closing?0:indentUnit);},electricChars:"{}",blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//"};});(function(){function words(str){var obj={},words=str.split(" ");for(var i=0;i<words.length;++i)obj[words[i]]=true;return obj;}
+var cKeywords="auto if break int case long char register continue return default short do sizeof "+"double static else struct entry switch extern typedef float union for unsigned "+"goto while enum void const signed volatile";function cppHook(stream,state){if(!state.startOfLine)return false;for(;;){if(stream.skipTo("\\")){stream.next();if(stream.eol()){state.tokenize=cppHook;break;}}else{stream.skipToEnd();state.tokenize=null;break;}}
+return"meta";}
+function tokenAtString(stream,state){var next;while((next=stream.next())!=null){if(next=='"'&&!stream.eat('"')){state.tokenize=null;break;}}
+return"string";}
+function mimes(ms,mode){for(var i=0;i<ms.length;++i)CodeMirror.defineMIME(ms[i],mode);}
+mimes(["text/x-csrc","text/x-c","text/x-chdr"],{name:"clike",keywords:words(cKeywords),blockKeywords:words("case do else for if switch while struct"),atoms:words("null"),hooks:{"#":cppHook}});mimes(["text/x-c++src","text/x-c++hdr"],{name:"clike",keywords:words(cKeywords+" asm dynamic_cast namespace reinterpret_cast try bool explicit new "+"static_cast typeid catch operator template typename class friend private "+"this using const_cast inline public throw virtual delete mutable protected "+"wchar_t"),blockKeywords:words("catch class do else finally for if struct switch try while"),atoms:words("true false null"),hooks:{"#":cppHook}});CodeMirror.defineMIME("text/x-java",{name:"clike",keywords:words("abstract assert boolean break byte case catch char class const continue default "+"do double else enum extends final finally float for goto if implements import "+"instanceof int interface long native new package private protected public "+"return short static strictfp super switch synchronized this throw throws transient "+"try void volatile while"),blockKeywords:words("catch class do else finally for if switch try while"),atoms:words("true false null"),hooks:{"@":function(stream){stream.eatWhile(/[\w\$_]/);return"meta";}}});CodeMirror.defineMIME("text/x-csharp",{name:"clike",keywords:words("abstract as base break case catch checked class const continue"+" default delegate do else enum event explicit extern finally fixed for"+" foreach goto if implicit in interface internal is lock namespace new"+" operator out override params private protected public readonly ref return sealed"+" sizeof stackalloc static struct switch this throw try typeof unchecked"+" unsafe using virtual void volatile while add alias ascending descending dynamic from get"+" global group into join let orderby partial remove select set value var yield"),blockKeywords:words("catch class do else finally for foreach if struct switch try while"),builtin:words("Boolean Byte Char DateTime DateTimeOffset Decimal Double"+" Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32"+" UInt64 bool byte char decimal double short int long object"+" sbyte float string ushort uint ulong"),atoms:words("true false null"),hooks:{"@":function(stream,state){if(stream.eat('"')){state.tokenize=tokenAtString;return tokenAtString(stream,state);}
+stream.eatWhile(/[\w\$_]/);return"meta";}}});CodeMirror.defineMIME("text/x-scala",{name:"clike",keywords:words("abstract case catch class def do else extends false final finally for forSome if "+"implicit import lazy match new null object override package private protected return "+"sealed super this throw trait try trye type val var while with yield _ : = => <- <: "+"<% >: # @ "+"assert assume require print println printf readLine readBoolean readByte readShort "+"readChar readInt readLong readFloat readDouble "+"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either "+"Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable "+"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering "+"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder "+"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: "+"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable "+"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process "+"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String "+"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"),blockKeywords:words("catch class do else finally for forSome if match switch try while"),atoms:words("true false null"),hooks:{"@":function(stream){stream.eatWhile(/[\w\$_]/);return"meta";}}});mimes(["x-shader/x-vertex","x-shader/x-fragment"],{name:"clike",keywords:words("float int bool void "+"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 "+"mat2 mat3 mat4 "+"sampler1D sampler2D sampler3D samplerCube "+"sampler1DShadow sampler2DShadow"+"const attribute uniform varying "+"break continue discard return "+"for while do if else struct "+"in out inout"),blockKeywords:words("for while do if else struct"),builtin:words("radians degrees sin cos tan asin acos atan "+"pow exp log exp2 sqrt inversesqrt "+"abs sign floor ceil fract mod min max clamp mix step smootstep "+"length distance dot cross normalize ftransform faceforward "+"reflect refract matrixCompMult "+"lessThan lessThanEqual greaterThan greaterThanEqual "+"equal notEqual any all not "+"texture1D texture1DProj texture1DLod texture1DProjLod "+"texture2D texture2DProj texture2DLod texture2DProjLod "+"texture3D texture3DProj texture3DLod texture3DProjLod "+"textureCube textureCubeLod "+"shadow1D shadow2D shadow1DProj shadow2DProj "+"shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod "+"dFdx dFdy fwidth "+"noise1 noise2 noise3 noise4"),atoms:words("true false "+"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex "+"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 "+"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 "+"gl_FogCoord "+"gl_Position gl_PointSize gl_ClipVertex "+"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor "+"gl_TexCoord gl_FogFragCoord "+"gl_FragCoord gl_FrontFacing "+"gl_FragColor gl_FragData gl_FragDepth "+"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix "+"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse "+"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse "+"gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose "+"gl_ProjectionMatrixInverseTranspose "+"gl_ModelViewProjectionMatrixInverseTranspose "+"gl_TextureMatrixInverseTranspose "+"gl_NormalScale gl_DepthRange gl_ClipPlane "+"gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel "+"gl_FrontLightModelProduct gl_BackLightModelProduct "+"gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ "+"gl_FogParameters "+"gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords "+"gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats "+"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits "+"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits "+"gl_MaxDrawBuffers"),hooks:{"#":cppHook}});}());;CodeMirror.defineMode('coffeescript',function(conf){var ERRORCLASS='error';function wordRegexp(words){return new RegExp("^(("+words.join(")|(")+"))\\b");}
+var singleOperators=new RegExp("^[\\+\\-\\*/%&|\\^~<>!\?]");var singleDelimiters=new RegExp('^[\\(\\)\\[\\]\\{\\},:`=;\\.]');var doubleOperators=new RegExp("^((\->)|(\=>)|(\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))");var doubleDelimiters=new RegExp("^((\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");var tripleDelimiters=new RegExp("^((\\.\\.\\.)|(//=)|(>>=)|(<<=)|(\\*\\*=))");var identifiers=new RegExp("^[_A-Za-z$][_A-Za-z$0-9]*");var properties=new RegExp("^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*");var wordOperators=wordRegexp(['and','or','not','is','isnt','in','instanceof','typeof']);var indentKeywords=['for','while','loop','if','unless','else','switch','try','catch','finally','class'];var commonKeywords=['break','by','continue','debugger','delete','do','in','of','new','return','then','this','throw','when','until'];var keywords=wordRegexp(indentKeywords.concat(commonKeywords));indentKeywords=wordRegexp(indentKeywords);var stringPrefixes=new RegExp("^('{3}|\"{3}|['\"])");var regexPrefixes=new RegExp("^(/{3}|/)");var commonConstants=['Infinity','NaN','undefined','null','true','false','on','off','yes','no'];var constants=wordRegexp(commonConstants);function tokenBase(stream,state){if(stream.sol()){var scopeOffset=state.scopes[0].offset;if(stream.eatSpace()){var lineOffset=stream.indentation();if(lineOffset>scopeOffset){return'indent';}else if(lineOffset<scopeOffset){return'dedent';}
+return null;}else{if(scopeOffset>0){dedent(stream,state);}}}
+if(stream.eatSpace()){return null;}
+var ch=stream.peek();if(stream.match("####")){stream.skipToEnd();return'comment';}
+if(stream.match("###")){state.tokenize=longComment;return state.tokenize(stream,state);}
+if(ch==='#'){stream.skipToEnd();return'comment';}
+if(stream.match(/^-?[0-9\.]/,false)){var floatLiteral=false;if(stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)){floatLiteral=true;}
+if(stream.match(/^-?\d+\.\d*/)){floatLiteral=true;}
+if(stream.match(/^-?\.\d+/)){floatLiteral=true;}
+if(floatLiteral){if(stream.peek()=="."){stream.backUp(1);}
+return'number';}
+var intLiteral=false;if(stream.match(/^-?0x[0-9a-f]+/i)){intLiteral=true;}
+if(stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)){intLiteral=true;}
+if(stream.match(/^-?0(?![\dx])/i)){intLiteral=true;}
+if(intLiteral){return'number';}}
+if(stream.match(stringPrefixes)){state.tokenize=tokenFactory(stream.current(),'string');return state.tokenize(stream,state);}
+if(stream.match(regexPrefixes)){if(stream.current()!='/'||stream.match(/^.*\//,false)){state.tokenize=tokenFactory(stream.current(),'string-2');return state.tokenize(stream,state);}else{stream.backUp(1);}}
+if(stream.match(tripleDelimiters)||stream.match(doubleDelimiters)){return'punctuation';}
+if(stream.match(doubleOperators)||stream.match(singleOperators)||stream.match(wordOperators)){return'operator';}
+if(stream.match(singleDelimiters)){return'punctuation';}
+if(stream.match(constants)){return'atom';}
+if(stream.match(keywords)){return'keyword';}
+if(stream.match(identifiers)){return'variable';}
+if(stream.match(properties)){return'property';}
+stream.next();return ERRORCLASS;}
+function tokenFactory(delimiter,outclass){var singleline=delimiter.length==1;return function(stream,state){while(!stream.eol()){stream.eatWhile(/[^'"\/\\]/);if(stream.eat('\\')){stream.next();if(singleline&&stream.eol()){return outclass;}}else if(stream.match(delimiter)){state.tokenize=tokenBase;return outclass;}else{stream.eat(/['"\/]/);}}
+if(singleline){if(conf.mode.singleLineStringErrors){outclass=ERRORCLASS;}else{state.tokenize=tokenBase;}}
+return outclass;};}
+function longComment(stream,state){while(!stream.eol()){stream.eatWhile(/[^#]/);if(stream.match("###")){state.tokenize=tokenBase;break;}
+stream.eatWhile("#");}
+return"comment";}
+function indent(stream,state,type){type=type||'coffee';var indentUnit=0;if(type==='coffee'){for(var i=0;i<state.scopes.length;i++){if(state.scopes[i].type==='coffee'){indentUnit=state.scopes[i].offset+conf.indentUnit;break;}}}else{indentUnit=stream.column()+stream.current().length;}
+state.scopes.unshift({offset:indentUnit,type:type});}
+function dedent(stream,state){if(state.scopes.length==1)return;if(state.scopes[0].type==='coffee'){var _indent=stream.indentation();var _indent_index=-1;for(var i=0;i<state.scopes.length;++i){if(_indent===state.scopes[i].offset){_indent_index=i;break;}}
+if(_indent_index===-1){return true;}
+while(state.scopes[0].offset!==_indent){state.scopes.shift();}
+return false;}else{state.scopes.shift();return false;}}
+function tokenLexer(stream,state){var style=state.tokenize(stream,state);var current=stream.current();if(current==='.'){style=state.tokenize(stream,state);current=stream.current();if(style==='variable'){return'variable';}else{return ERRORCLASS;}}
+if(current==='return'){state.dedent+=1;}
+if(((current==='->'||current==='=>')&&!state.lambda&&state.scopes[0].type=='coffee'&&stream.peek()==='')||style==='indent'){indent(stream,state);}
+var delimiter_index='[({'.indexOf(current);if(delimiter_index!==-1){indent(stream,state,'])}'.slice(delimiter_index,delimiter_index+1));}
+if(indentKeywords.exec(current)){indent(stream,state);}
+if(current=='then'){dedent(stream,state);}
+if(style==='dedent'){if(dedent(stream,state)){return ERRORCLASS;}}
+delimiter_index='])}'.indexOf(current);if(delimiter_index!==-1){if(dedent(stream,state)){return ERRORCLASS;}}
+if(state.dedent>0&&stream.eol()&&state.scopes[0].type=='coffee'){if(state.scopes.length>1)state.scopes.shift();state.dedent-=1;}
+return style;}
+var external={startState:function(basecolumn){return{tokenize:tokenBase,scopes:[{offset:basecolumn||0,type:'coffee'}],lastToken:null,lambda:false,dedent:0};},token:function(stream,state){var style=tokenLexer(stream,state);state.lastToken={style:style,content:stream.current()};if(stream.eol()&&stream.lambda){state.lambda=false;}
+return style;},indent:function(state){if(state.tokenize!=tokenBase){return 0;}
+return state.scopes[0].offset;},lineComment:"#"};return external;});CodeMirror.defineMIME('text/x-coffeescript','coffeescript');;(function(){function keywords(str){var obj={},words=str.split(" ");for(var i=0;i<words.length;++i)obj[words[i]]=true;return obj;}
+function heredoc(delim){return function(stream,state){if(stream.match(delim))state.tokenize=null;else stream.skipToEnd();return"string";};}
+var phpConfig={name:"clike",keywords:keywords("abstract and array as break case catch class clone const continue declare default "+"do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final "+"for foreach function global goto if implements interface instanceof namespace "+"new or private protected public static switch throw trait try use var while xor "+"die echo empty exit eval include include_once isset list require require_once return "+"print unset __halt_compiler self static parent"),blockKeywords:keywords("catch do else elseif for foreach if switch try while"),atoms:keywords("true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__"),builtin:keywords("func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport echo print global static exit array empty eval isset unset die include require include_once require_once"),multiLineStrings:true,hooks:{"$":function(stream){stream.eatWhile(/[\w\$_]/);return"variable-2";},"<":function(stream,state){if(stream.match(/<</)){stream.eatWhile(/[\w\.]/);state.tokenize=heredoc(stream.current().slice(3));return state.tokenize(stream,state);}
+return false;},"#":function(stream){while(!stream.eol()&&!stream.match("?>",false))stream.next();return"comment";},"/":function(stream){if(stream.eat("/")){while(!stream.eol()&&!stream.match("?>",false))stream.next();return"comment";}
+return false;}}};CodeMirror.defineMode("php",function(config,parserConfig){var htmlMode=CodeMirror.getMode(config,"text/html");var phpMode=CodeMirror.getMode(config,phpConfig);function dispatch(stream,state){var isPHP=state.curMode==phpMode;if(stream.sol()&&state.pending!='"')state.pending=null;if(!isPHP){if(stream.match(/^<\?\w*/)){state.curMode=phpMode;state.curState=state.php;return"meta";}
+if(state.pending=='"'){while(!stream.eol()&&stream.next()!='"'){}
+var style="string";}else if(state.pending&&stream.pos<state.pending.end){stream.pos=state.pending.end;var style=state.pending.style;}else{var style=htmlMode.token(stream,state.curState);}
+state.pending=null;var cur=stream.current(),openPHP=cur.search(/<\?/);if(openPHP!=-1){if(style=="string"&&/\"$/.test(cur)&&!/\?>/.test(cur))state.pending='"';else state.pending={end:stream.pos,style:style};stream.backUp(cur.length-openPHP);}
+return style;}else if(isPHP&&state.php.tokenize==null&&stream.match("?>")){state.curMode=htmlMode;state.curState=state.html;return"meta";}else{return phpMode.token(stream,state.curState);}}
+return{startState:function(){var html=CodeMirror.startState(htmlMode),php=CodeMirror.startState(phpMode);return{html:html,php:php,curMode:parserConfig.startOpen?phpMode:htmlMode,curState:parserConfig.startOpen?php:html,pending:null};},copyState:function(state){var html=state.html,htmlNew=CodeMirror.copyState(htmlMode,html),php=state.php,phpNew=CodeMirror.copyState(phpMode,php),cur;if(state.curMode==htmlMode)cur=htmlNew;else cur=phpNew;return{html:htmlNew,php:phpNew,curMode:state.curMode,curState:cur,pending:state.pending};},token:dispatch,indent:function(state,textAfter){if((state.curMode!=phpMode&&/^\s*<\//.test(textAfter))||(state.curMode==phpMode&&/^\?>/.test(textAfter)))
+return htmlMode.indent(state.html,textAfter);return state.curMode.indent(state.curState,textAfter);},electricChars:"/{}:",blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",innerMode:function(state){return{state:state.curState,mode:state.curMode};}};},"htmlmixed","clike");CodeMirror.defineMIME("application/x-httpd-php","php");CodeMirror.defineMIME("application/x-httpd-php-open",{name:"php",startOpen:true});CodeMirror.defineMIME("text/x-php",phpConfig);})();;CodeMirror.defineMode("python",function(conf,parserConf){var ERRORCLASS='error';function wordRegexp(words){return new RegExp("^(("+words.join(")|(")+"))\\b");}
+var singleOperators=parserConf.singleOperators||new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");var singleDelimiters=parserConf.singleDelimiters||new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');var doubleOperators=parserConf.doubleOperators||new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");var doubleDelimiters=parserConf.doubleDelimiters||new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");var tripleDelimiters=parserConf.tripleDelimiters||new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");var identifiers=parserConf.identifiers||new RegExp("^[_A-Za-z][_A-Za-z0-9]*");var wordOperators=wordRegexp(['and','or','not','is','in']);var commonkeywords=['as','assert','break','class','continue','def','del','elif','else','except','finally','for','from','global','if','import','lambda','pass','raise','return','try','while','with','yield'];var commonBuiltins=['abs','all','any','bin','bool','bytearray','callable','chr','classmethod','compile','complex','delattr','dict','dir','divmod','enumerate','eval','filter','float','format','frozenset','getattr','globals','hasattr','hash','help','hex','id','input','int','isinstance','issubclass','iter','len','list','locals','map','max','memoryview','min','next','object','oct','open','ord','pow','property','range','repr','reversed','round','set','setattr','slice','sorted','staticmethod','str','sum','super','tuple','type','vars','zip','__import__','NotImplemented','Ellipsis','__debug__'];var py2={'builtins':['apply','basestring','buffer','cmp','coerce','execfile','file','intern','long','raw_input','reduce','reload','unichr','unicode','xrange','False','True','None'],'keywords':['exec','print']};var py3={'builtins':['ascii','bytes','exec','print'],'keywords':['nonlocal','False','True','None']};if(!!parserConf.version&&parseInt(parserConf.version,10)===3){commonkeywords=commonkeywords.concat(py3.keywords);commonBuiltins=commonBuiltins.concat(py3.builtins);var stringPrefixes=new RegExp("^(([rb]|(br))?('{3}|\"{3}|['\"]))","i");}else{commonkeywords=commonkeywords.concat(py2.keywords);commonBuiltins=commonBuiltins.concat(py2.builtins);var stringPrefixes=new RegExp("^(([rub]|(ur)|(br))?('{3}|\"{3}|['\"]))","i");}
+var keywords=wordRegexp(commonkeywords);var builtins=wordRegexp(commonBuiltins);var indentInfo=null;function tokenBase(stream,state){if(stream.sol()){var scopeOffset=state.scopes[0].offset;if(stream.eatSpace()){var lineOffset=stream.indentation();if(lineOffset>scopeOffset){indentInfo='indent';}else if(lineOffset<scopeOffset){indentInfo='dedent';}
+return null;}else{if(scopeOffset>0){dedent(stream,state);}}}
+if(stream.eatSpace()){return null;}
+var ch=stream.peek();if(ch==='#'){stream.skipToEnd();return'comment';}
+if(stream.match(/^[0-9\.]/,false)){var floatLiteral=false;if(stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)){floatLiteral=true;}
+if(stream.match(/^\d+\.\d*/)){floatLiteral=true;}
+if(stream.match(/^\.\d+/)){floatLiteral=true;}
+if(floatLiteral){stream.eat(/J/i);return'number';}
+var intLiteral=false;if(stream.match(/^0x[0-9a-f]+/i)){intLiteral=true;}
+if(stream.match(/^0b[01]+/i)){intLiteral=true;}
+if(stream.match(/^0o[0-7]+/i)){intLiteral=true;}
+if(stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)){stream.eat(/J/i);intLiteral=true;}
+if(stream.match(/^0(?![\dx])/i)){intLiteral=true;}
+if(intLiteral){stream.eat(/L/i);return'number';}}
+if(stream.match(stringPrefixes)){state.tokenize=tokenStringFactory(stream.current());return state.tokenize(stream,state);}
+if(stream.match(tripleDelimiters)||stream.match(doubleDelimiters)){return null;}
+if(stream.match(doubleOperators)||stream.match(singleOperators)||stream.match(wordOperators)){return'operator';}
+if(stream.match(singleDelimiters)){return null;}
+if(stream.match(keywords)){return'keyword';}
+if(stream.match(builtins)){return'builtin';}
+if(stream.match(identifiers)){return'variable';}
+stream.next();return ERRORCLASS;}
+function tokenStringFactory(delimiter){while('rub'.indexOf(delimiter.charAt(0).toLowerCase())>=0){delimiter=delimiter.substr(1);}
+var singleline=delimiter.length==1;var OUTCLASS='string';function tokenString(stream,state){while(!stream.eol()){stream.eatWhile(/[^'"\\]/);if(stream.eat('\\')){stream.next();if(singleline&&stream.eol()){return OUTCLASS;}}else if(stream.match(delimiter)){state.tokenize=tokenBase;return OUTCLASS;}else{stream.eat(/['"]/);}}
+if(singleline){if(parserConf.singleLineStringErrors){return ERRORCLASS;}else{state.tokenize=tokenBase;}}
+return OUTCLASS;}
+tokenString.isString=true;return tokenString;}
+function indent(stream,state,type){type=type||'py';var indentUnit=0;if(type==='py'){if(state.scopes[0].type!=='py'){state.scopes[0].offset=stream.indentation();return;}
+for(var i=0;i<state.scopes.length;++i){if(state.scopes[i].type==='py'){indentUnit=state.scopes[i].offset+conf.indentUnit;break;}}}else{indentUnit=stream.column()+stream.current().length;}
+state.scopes.unshift({offset:indentUnit,type:type});}
+function dedent(stream,state,type){type=type||'py';if(state.scopes.length==1)return;if(state.scopes[0].type==='py'){var _indent=stream.indentation();var _indent_index=-1;for(var i=0;i<state.scopes.length;++i){if(_indent===state.scopes[i].offset){_indent_index=i;break;}}
+if(_indent_index===-1){return true;}
+while(state.scopes[0].offset!==_indent){state.scopes.shift();}
+return false;}else{if(type==='py'){state.scopes[0].offset=stream.indentation();return false;}else{if(state.scopes[0].type!=type){return true;}
+state.scopes.shift();return false;}}}
+function tokenLexer(stream,state){indentInfo=null;var style=state.tokenize(stream,state);var current=stream.current();if(current==='.'){style=stream.match(identifiers,false)?null:ERRORCLASS;if(style===null&&state.lastToken==='meta'){style='meta';}
+return style;}
+if(current==='@'){return stream.match(identifiers,false)?'meta':ERRORCLASS;}
+if((style==='variable'||style==='builtin')&&state.lastToken==='meta'){style='meta';}
+if(current==='pass'||current==='return'){state.dedent+=1;}
+if(current==='lambda')state.lambda=true;if((current===':'&&!state.lambda&&state.scopes[0].type=='py')||indentInfo==='indent'){indent(stream,state);}
+var delimiter_index='[({'.indexOf(current);if(delimiter_index!==-1){indent(stream,state,'])}'.slice(delimiter_index,delimiter_index+1));}
+if(indentInfo==='dedent'){if(dedent(stream,state)){return ERRORCLASS;}}
+delimiter_index='])}'.indexOf(current);if(delimiter_index!==-1){if(dedent(stream,state,current)){return ERRORCLASS;}}
+if(state.dedent>0&&stream.eol()&&state.scopes[0].type=='py'){if(state.scopes.length>1)state.scopes.shift();state.dedent-=1;}
+return style;}
+var external={startState:function(basecolumn){return{tokenize:tokenBase,scopes:[{offset:basecolumn||0,type:'py'}],lastToken:null,lambda:false,dedent:0};},token:function(stream,state){var style=tokenLexer(stream,state);state.lastToken=style;if(stream.eol()&&stream.lambda){state.lambda=false;}
+return style;},indent:function(state){if(state.tokenize!=tokenBase){return state.tokenize.isString?CodeMirror.Pass:0;}
+return state.scopes[0].offset;},lineComment:"#"};return external;});CodeMirror.defineMIME("text/x-python","python");;CodeMirror.defineMode('shell',function(){var words={};function define(style,string){var split=string.split(' ');for(var i=0;i<split.length;i++){words[split[i]]=style;}};define('atom','true false');define('keyword','if then do else elif while until for in esac fi fin '+'fil done exit set unset export function');define('builtin','ab awk bash beep cat cc cd chown chmod chroot clear cp '+'curl cut diff echo find gawk gcc get git grep kill killall ln ls make '+'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh '+'shopt shred source sort sleep ssh start stop su sudo tee telnet top '+'touch vi vim wall wc wget who write yes zsh');function tokenBase(stream,state){var sol=stream.sol();var ch=stream.next();if(ch==='\''||ch==='"'||ch==='`'){state.tokens.unshift(tokenString(ch));return tokenize(stream,state);}
+if(ch==='#'){if(sol&&stream.eat('!')){stream.skipToEnd();return'meta';}
+stream.skipToEnd();return'comment';}
+if(ch==='$'){state.tokens.unshift(tokenDollar);return tokenize(stream,state);}
+if(ch==='+'||ch==='='){return'operator';}
+if(ch==='-'){stream.eat('-');stream.eatWhile(/\w/);return'attribute';}
+if(/\d/.test(ch)){stream.eatWhile(/\d/);if(!/\w/.test(stream.peek())){return'number';}}
+stream.eatWhile(/[\w-]/);var cur=stream.current();if(stream.peek()==='='&&/\w+/.test(cur))return'def';return words.hasOwnProperty(cur)?words[cur]:null;}
+function tokenString(quote){return function(stream,state){var next,end=false,escaped=false;while((next=stream.next())!=null){if(next===quote&&!escaped){end=true;break;}
+if(next==='$'&&!escaped&&quote!=='\''){escaped=true;stream.backUp(1);state.tokens.unshift(tokenDollar);break;}
+escaped=!escaped&&next==='\\';}
+if(end||!escaped){state.tokens.shift();}
+return(quote==='`'||quote===')'?'quote':'string');};};var tokenDollar=function(stream,state){if(state.tokens.length>1)stream.eat('$');var ch=stream.next(),hungry=/\w/;if(ch==='{')hungry=/[^}]/;if(ch==='('){state.tokens[0]=tokenString(')');return tokenize(stream,state);}
+if(!/\d/.test(ch)){stream.eatWhile(hungry);stream.eat('}');}
+state.tokens.shift();return'def';};function tokenize(stream,state){return(state.tokens[0]||tokenBase)(stream,state);};return{startState:function(){return{tokens:[]};},token:function(stream,state){if(stream.eatSpace())return null;return tokenize(stream,state);}};});CodeMirror.defineMIME('text/x-sh','shell');;WebInspector.CodeMirrorUtils={createTokenizer:function(mimeType)
+{var mode=CodeMirror.getMode({indentUnit:2},mimeType);var state=CodeMirror.startState(mode);function tokenize(line,callback)
+{var stream=new CodeMirror.StringStream(line);while(!stream.eol()){var style=mode.token(stream,state);var value=stream.current();callback(value,style,stream.start,stream.start+value.length);stream.start=stream.pos;}}
+return tokenize;},convertTokenType:function(tokenType)
+{if(tokenType.startsWith("js-variable")||tokenType.startsWith("js-property")||tokenType==="js-def")
+return"javascript-ident";if(tokenType==="js-string-2")
+return"javascript-regexp";if(tokenType==="js-number"||tokenType==="js-comment"||tokenType==="js-string"||tokenType==="js-keyword")
+return"javascript-"+tokenType.substring("js-".length);return null;},overrideModeWithPrefixedTokens:function(modeName,tokenPrefix)
+{var oldModeName=modeName+"-old";if(CodeMirror.modes[oldModeName])
+return;CodeMirror.defineMode(oldModeName,CodeMirror.modes[modeName]);CodeMirror.defineMode(modeName,modeConstructor);function modeConstructor(config,parserConfig)
+{var innerConfig={};for(var i in parserConfig)
+innerConfig[i]=parserConfig[i];innerConfig.name=oldModeName;var codeMirrorMode=CodeMirror.getMode(config,innerConfig);codeMirrorMode.name=modeName;codeMirrorMode.token=tokenOverride.bind(this,codeMirrorMode.token);return codeMirrorMode;}
+function tokenOverride(superToken,stream,state)
+{var token=superToken(stream,state);return token?tokenPrefix+token:token;}}}
+WebInspector.CodeMirrorUtils.overrideModeWithPrefixedTokens("css-base","css-");WebInspector.CodeMirrorUtils.overrideModeWithPrefixedTokens("javascript","js-");WebInspector.CodeMirrorUtils.overrideModeWithPrefixedTokens("xml","xml-");;WebInspector.CodeMirrorTextEditor=function(url,delegate)
+{WebInspector.View.call(this);this._delegate=delegate;this._url=url;this.registerRequiredCSS("cm/codemirror.css");this.registerRequiredCSS("cm/cmdevtools.css");this._codeMirror=window.CodeMirror(this.element,{lineNumbers:true,gutters:["CodeMirror-linenumbers"],matchBrackets:true,smartIndent:false,styleSelectedText:true,electricChars:false,autoCloseBrackets:{explode:false}});this._codeMirror._codeMirrorTextEditor=this;CodeMirror.keyMap["devtools-common"]={"Left":"goCharLeft","Right":"goCharRight","Up":"goLineUp","Down":"goLineDown","End":"goLineEnd","Home":"goLineStartSmart","PageUp":"goPageUp","PageDown":"goPageDown","Delete":"delCharAfter","Backspace":"delCharBefore","Tab":"defaultTab","Shift-Tab":"indentLess","Enter":"smartNewlineAndIndent","Ctrl-Space":"autocomplete"};CodeMirror.keyMap["devtools-pc"]={"Ctrl-A":"selectAll","Ctrl-Z":"undoAndReveal","Shift-Ctrl-Z":"redoAndReveal","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-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-/":"toggleComment",fallthrough:"devtools-common"};CodeMirror.keyMap["devtools-mac"]={"Cmd-A":"selectAll","Cmd-Z":"undoAndReveal","Shift-Cmd-Z":"redoAndReveal","Cmd-Up":"goDocStart","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineStartSmart","Cmd-Right":"goLineEnd","Alt-Backspace":"delGroupBefore","Alt-Delete":"delGroupAfter","Cmd-/":"toggleComment",fallthrough:"devtools-common"};WebInspector.settings.textEditorIndent.addChangeListener(this._updateEditorIndentation,this);this._updateEditorIndentation();WebInspector.settings.showWhitespacesInEditor.addChangeListener(this._updateCodeMirrorMode,this);this._codeMirror.setOption("keyMap",WebInspector.isMac()?"devtools-mac":"devtools-pc");this._codeMirror.setOption("flattenSpans",false);this._codeMirror.setOption("maxHighlightLength",1000);this._codeMirror.setOption("mode",null);this._shouldClearHistory=true;this._lineSeparator="\n";this._tokenHighlighter=new WebInspector.CodeMirrorTextEditor.TokenHighlighter(this._codeMirror);this._blockIndentController=new WebInspector.CodeMirrorTextEditor.BlockIndentController(this._codeMirror);this._fixWordMovement=new WebInspector.CodeMirrorTextEditor.FixWordMovement(this._codeMirror);this._autocompleteController=new WebInspector.CodeMirrorTextEditor.AutocompleteController(this,this._codeMirror);this._codeMirror.on("change",this._change.bind(this));this._codeMirror.on("beforeChange",this._beforeChange.bind(this));this._codeMirror.on("gutterClick",this._gutterClick.bind(this));this._codeMirror.on("cursorActivity",this._cursorActivity.bind(this));this._codeMirror.on("scroll",this._scroll.bind(this));this._codeMirror.on("focus",this._focus.bind(this));this._codeMirror.on("blur",this._blur.bind(this));this.element.addEventListener("contextmenu",this._contextMenu.bind(this),false);this.element.addStyleClass("fill");this.element.style.overflow="hidden";this.element.firstChild.addStyleClass("source-code");this.element.firstChild.addStyleClass("fill");this._elementToWidget=new Map();this._nestedUpdatesCounter=0;this.element.addEventListener("focus",this._handleElementFocus.bind(this),false);this.element.addEventListener("keydown",this._handleKeyDown.bind(this),true);this.element.tabIndex=0;this._setupSelectionColor();this._setupWhitespaceHighlight();}
+WebInspector.CodeMirrorTextEditor.autocompleteCommand=function(codeMirror)
+{codeMirror._codeMirrorTextEditor._autocompleteController.autocomplete();}
+CodeMirror.commands.autocomplete=WebInspector.CodeMirrorTextEditor.autocompleteCommand;CodeMirror.commands.smartNewlineAndIndent=function(codeMirror)
+{codeMirror.operation(innerSmartNewlineAndIndent.bind(this,codeMirror));function countIndent(line)
+{for(var i=0;i<line.length;++i){if(!WebInspector.TextUtils.isSpaceChar(line[i]))
+return i;}
+return line.length;}
+function innerSmartNewlineAndIndent(codeMirror)
+{var cur=codeMirror.getCursor("start");var line=codeMirror.getLine(cur.line);var indent=cur.line>0?countIndent(line):0;if(cur.ch<=indent){codeMirror.replaceSelection("\n"+line.substring(0,cur.ch),"end","+input");codeMirror.setSelection(new CodeMirror.Pos(cur.line+1,cur.ch));}else
+codeMirror.execCommand("newlineAndIndent");}}
+CodeMirror.commands.undoAndReveal=function(codemirror)
+{var scrollInfo=codemirror.getScrollInfo();codemirror.execCommand("undo");var cursor=codemirror.getCursor("start");codemirror._codeMirrorTextEditor._innerRevealLine(cursor.line,scrollInfo);}
+CodeMirror.commands.redoAndReveal=function(codemirror)
+{var scrollInfo=codemirror.getScrollInfo();codemirror.execCommand("redo");var cursor=codemirror.getCursor("start");codemirror._codeMirrorTextEditor._innerRevealLine(cursor.line,scrollInfo);}
+WebInspector.CodeMirrorTextEditor.LongLineModeLineLengthThreshold=2000;WebInspector.CodeMirrorTextEditor.MaximumNumberOfWhitespacesPerSingleSpan=16;WebInspector.CodeMirrorTextEditor.prototype={wasShown:function()
+{this._codeMirror.refresh();},_guessIndentationLevel:function()
+{var tabRegex=/^\t+/;var tabLines=0;var indents={};function processLine(lineHandle)
+{var text=lineHandle.text;if(text.length===0||!WebInspector.TextUtils.isSpaceChar(text[0]))
+return;if(tabRegex.test(text)){++tabLines;return;}
+var i=0;while(i<text.length&&WebInspector.TextUtils.isSpaceChar(text[i]))
+++i;if(i%2!==0)
+return;indents[i]=1+(indents[i]||0);}
+this._codeMirror.eachLine(processLine);var onePercentFilterThreshold=this.linesCount/100;if(tabLines&&tabLines>onePercentFilterThreshold)
+return"\t";var minimumIndent=Infinity;for(var i in indents){if(indents[i]<onePercentFilterThreshold)
+continue;var indent=parseInt(i,10);if(minimumIndent>indent)
+minimumIndent=indent;}
+if(minimumIndent===Infinity)
+return WebInspector.TextUtils.Indent.FourSpaces;return new Array(minimumIndent+1).join(" ");},_updateEditorIndentation:function()
+{var extraKeys={};var indent=WebInspector.settings.textEditorIndent.get();if(WebInspector.settings.textEditorAutoDetectIndent.get())
+indent=this._guessIndentationLevel();if(indent===WebInspector.TextUtils.Indent.TabCharacter){this._codeMirror.setOption("indentWithTabs",true);this._codeMirror.setOption("indentUnit",4);}else{this._codeMirror.setOption("indentWithTabs",false);this._codeMirror.setOption("indentUnit",indent.length);extraKeys.Tab=function(codeMirror)
+{if(codeMirror.somethingSelected())
+return CodeMirror.Pass;var pos=codeMirror.getCursor("head");codeMirror.replaceRange(indent.substring(pos.ch%indent.length),codeMirror.getCursor());}}
+this._codeMirror.setOption("extraKeys",extraKeys);this._indentationLevel=indent;},indent:function()
+{return this._indentationLevel;},highlightSearchResults:function(regex,range)
+{function innerHighlightRegex()
+{if(range){this.revealLine(range.startLine);this.setSelection(WebInspector.TextRange.createFromLocation(range.startLine,range.startColumn));}else{this.setSelection(this.selection().collapseToEnd());}
+this._tokenHighlighter.highlightSearchResults(regex,range);}
+this._codeMirror.operation(innerHighlightRegex.bind(this));},cancelSearchResultsHighlight:function()
+{this._codeMirror.operation(this._tokenHighlighter.highlightSelectedTokens.bind(this._tokenHighlighter));},undo:function()
+{this._codeMirror.undo();},redo:function()
+{this._codeMirror.redo();},_setupSelectionColor:function()
+{if(WebInspector.CodeMirrorTextEditor._selectionStyleInjected)
+return;WebInspector.CodeMirrorTextEditor._selectionStyleInjected=true;var backgroundColor=WebInspector.getSelectionBackgroundColor();var backgroundColorRule=backgroundColor?".CodeMirror .CodeMirror-selected { background-color: "+backgroundColor+";}":"";var foregroundColor=WebInspector.getSelectionForegroundColor();var foregroundColorRule=foregroundColor?".CodeMirror .CodeMirror-selectedtext:not(.CodeMirror-persist-highlight) { color: "+foregroundColor+"!important;}":"";if(!foregroundColorRule&&!backgroundColorRule)
+return;var style=document.createElement("style");style.textContent=backgroundColorRule+foregroundColorRule;document.head.appendChild(style);},_setupWhitespaceHighlight:function()
+{if(WebInspector.CodeMirrorTextEditor._whitespaceStyleInjected||!WebInspector.settings.showWhitespacesInEditor.get())
+return;WebInspector.CodeMirrorTextEditor._whitespaceStyleInjected=true;const classBase=".cm-whitespace-";const spaceChar="ยท";var spaceChars="";var rules="";for(var i=1;i<=WebInspector.CodeMirrorTextEditor.MaximumNumberOfWhitespacesPerSingleSpan;++i){spaceChars+=spaceChar;var rule=classBase+i+"::before { content: '"+spaceChars+"';}\n";rules+=rule;}
+rules+=".cm-tab:before { display: block !important; }\n";var style=document.createElement("style");style.textContent=rules;document.head.appendChild(style);},_handleKeyDown:function(e)
+{if(this._autocompleteController.keyDown(e))
+e.consume(true);},_shouldProcessWordForAutocompletion:function(word)
+{return word.length&&(word[0]<'0'||word[0]>'9');},_addTextToCompletionDictionary:function(text)
+{var words=WebInspector.TextUtils.textToWords(text);for(var i=0;i<words.length;++i){if(this._shouldProcessWordForAutocompletion(words[i]))
+this._dictionary.addWord(words[i]);}},_removeTextFromCompletionDictionary:function(text)
+{var words=WebInspector.TextUtils.textToWords(text);for(var i=0;i<words.length;++i){if(this._shouldProcessWordForAutocompletion(words[i]))
+this._dictionary.removeWord(words[i]);}},setCompletionDictionary:function(dictionary)
+{this._dictionary=dictionary;this._addTextToCompletionDictionary(this.text());},cursorPositionToCoordinates:function(lineNumber,column)
+{if(lineNumber>=this._codeMirror.lineCount()||lineNumber<0||column<0||column>this._codeMirror.getLine(lineNumber).length)
+return null;var metrics=this._codeMirror.cursorCoords(new CodeMirror.Pos(lineNumber,column));return{x:metrics.left,y:metrics.top,height:metrics.bottom-metrics.top};},coordinatesToCursorPosition:function(x,y)
+{var element=document.elementFromPoint(x,y);if(!element||!element.isSelfOrDescendant(this._codeMirror.getWrapperElement()))
+return null;var gutterBox=this._codeMirror.getGutterElement().boxInWindow();if(x>=gutterBox.x&&x<=gutterBox.x+gutterBox.width&&y>=gutterBox.y&&y<=gutterBox.y+gutterBox.height)
+return null;var coords=this._codeMirror.coordsChar({left:x,top:y});return this._toRange(coords,coords);},tokenAtTextPosition:function(lineNumber,column)
+{if(lineNumber<0||lineNumber>=this._codeMirror.lineCount())
+return null;var token=this._codeMirror.getTokenAt(new CodeMirror.Pos(lineNumber,(column||0)+1));if(!token||!token.type)
+return null;var convertedType=WebInspector.CodeMirrorUtils.convertTokenType(token.type);if(!convertedType)
+return null;return{startColumn:token.start,endColumn:token.end-1,type:convertedType};},copyRange:function(textRange)
+{var pos=this._toPos(textRange.normalize());return this._codeMirror.getRange(pos.start,pos.end);},isClean:function()
+{return this._codeMirror.isClean();},markClean:function()
+{this._codeMirror.markClean();},_hasLongLines:function()
+{function lineIterator(lineHandle)
+{if(lineHandle.text.length>WebInspector.CodeMirrorTextEditor.LongLineModeLineLengthThreshold)
+hasLongLines=true;return hasLongLines;}
+var hasLongLines=false;this._codeMirror.eachLine(lineIterator);return hasLongLines;},_whitespaceOverlayMode:function(mimeType)
+{var modeName=CodeMirror.mimeModes[mimeType]+"+whitespaces";if(CodeMirror.modes[modeName])
+return modeName;function modeConstructor(config,parserConfig)
+{function nextToken(stream)
+{if(stream.peek()===" "){var spaces=0;while(spaces<WebInspector.CodeMirrorTextEditor.MaximumNumberOfWhitespacesPerSingleSpan&&stream.peek()===" "){++spaces;stream.next();}
+return"whitespace whitespace-"+spaces;}
+while(!stream.eol()&&stream.peek()!==" ")
+stream.next();return null;}
+var whitespaceMode={token:nextToken};return CodeMirror.overlayMode(CodeMirror.getMode(config,mimeType),whitespaceMode,false);}
+CodeMirror.defineMode(modeName,modeConstructor);return modeName;},_enableLongLinesMode:function()
+{this._codeMirror.setOption("styleSelectedText",false);this._longLinesMode=true;},_disableLongLinesMode:function()
+{this._codeMirror.setOption("styleSelectedText",true);this._longLinesMode=false;},_updateCodeMirrorMode:function()
+{var showWhitespaces=WebInspector.settings.showWhitespacesInEditor.get();this._codeMirror.setOption("mode",showWhitespaces?this._whitespaceOverlayMode(this._mimeType):this._mimeType);},setMimeType:function(mimeType)
+{this._mimeType=mimeType;if(this._hasLongLines())
+this._enableLongLinesMode();else
+this._disableLongLinesMode();this._updateCodeMirrorMode();},setReadOnly:function(readOnly)
+{this.element.enableStyleClass("CodeMirror-readonly",readOnly)
+this._codeMirror.setOption("readOnly",readOnly);},readOnly:function()
+{return!!this._codeMirror.getOption("readOnly");},removeHighlight:function(highlightDescriptor)
+{highlightDescriptor.clear();},highlightRange:function(range,cssClass)
+{cssClass="CodeMirror-persist-highlight "+cssClass;var pos=this._toPos(range);++pos.end.ch;return this._codeMirror.markText(pos.start,pos.end,{className:cssClass,startStyle:cssClass+"-start",endStyle:cssClass+"-end"});},highlightRegex:function(regex,cssClass){},defaultFocusedElement:function()
+{return this.element;},focus:function()
+{this._codeMirror.focus();},_handleElementFocus:function()
+{this._codeMirror.focus();},beginUpdates:function()
+{++this._nestedUpdatesCounter;},endUpdates:function()
+{if(!--this._nestedUpdatesCounter)
+this._codeMirror.refresh();},revealLine:function(lineNumber)
+{this._innerRevealLine(lineNumber,this._codeMirror.getScrollInfo());},_innerRevealLine:function(lineNumber,scrollInfo)
+{var topLine=this._codeMirror.lineAtHeight(scrollInfo.top,"local");var bottomLine=this._codeMirror.lineAtHeight(scrollInfo.top+scrollInfo.clientHeight,"local");var linesPerScreen=bottomLine-topLine+1;if(lineNumber<topLine){var topLineToReveal=Math.max(lineNumber-(linesPerScreen/2)+1,0)|0;this._codeMirror.scrollIntoView(new CodeMirror.Pos(topLineToReveal,0));}else if(lineNumber>bottomLine){var bottomLineToReveal=Math.min(lineNumber+(linesPerScreen/2)-1,this.linesCount-1)|0;this._codeMirror.scrollIntoView(new CodeMirror.Pos(bottomLineToReveal,0));}},_gutterClick:function(instance,lineNumber,gutter,event)
+{this.dispatchEventToListeners(WebInspector.TextEditor.Events.GutterClick,{lineNumber:lineNumber,event:event});},_contextMenu:function(event)
+{var contextMenu=new WebInspector.ContextMenu(event);var target=event.target.enclosingNodeOrSelfWithClass("CodeMirror-gutter-elt");if(target)
+this._delegate.populateLineGutterContextMenu(contextMenu,parseInt(target.textContent,10)-1);else
+this._delegate.populateTextAreaContextMenu(contextMenu,0);contextMenu.show();},addBreakpoint:function(lineNumber,disabled,conditional)
+{if(lineNumber<0||lineNumber>=this._codeMirror.lineCount())
+return;var className="cm-breakpoint"+(conditional?" cm-breakpoint-conditional":"")+(disabled?" cm-breakpoint-disabled":"");this._codeMirror.addLineClass(lineNumber,"wrap",className);},removeBreakpoint:function(lineNumber)
+{if(lineNumber<0||lineNumber>=this._codeMirror.lineCount())
+return;var wrapClasses=this._codeMirror.getLineHandle(lineNumber).wrapClass;if(!wrapClasses)
+return;var classes=wrapClasses.split(" ");for(var i=0;i<classes.length;++i){if(classes[i].startsWith("cm-breakpoint"))
+this._codeMirror.removeLineClass(lineNumber,"wrap",classes[i]);}},setExecutionLine:function(lineNumber)
+{this._executionLine=this._codeMirror.getLineHandle(lineNumber);this._codeMirror.addLineClass(this._executionLine,"wrap","cm-execution-line");},clearExecutionLine:function()
+{if(this._executionLine)
+this._codeMirror.removeLineClass(this._executionLine,"wrap","cm-execution-line");delete this._executionLine;},addDecoration:function(lineNumber,element)
+{var widget=this._codeMirror.addLineWidget(lineNumber,element);this._elementToWidget.put(element,widget);},removeDecoration:function(lineNumber,element)
+{var widget=this._elementToWidget.remove(element);if(widget)
+this._codeMirror.removeLineWidget(widget);},highlightPosition:function(lineNumber,columnNumber)
+{if(lineNumber<0)
+return;lineNumber=Math.min(lineNumber,this._codeMirror.lineCount()-1);if(typeof columnNumber!=="number"||columnNumber<0||columnNumber>this._codeMirror.getLine(lineNumber).length)
+columnNumber=0;this.clearPositionHighlight();this._highlightedLine=this._codeMirror.getLineHandle(lineNumber);if(!this._highlightedLine)
+return;this.revealLine(lineNumber);this._codeMirror.addLineClass(this._highlightedLine,null,"cm-highlight");this._clearHighlightTimeout=setTimeout(this.clearPositionHighlight.bind(this),2000);if(!this.readOnly())
+this._codeMirror.setSelection(new CodeMirror.Pos(lineNumber,columnNumber));},clearPositionHighlight:function()
+{if(this._clearHighlightTimeout)
+clearTimeout(this._clearHighlightTimeout);delete this._clearHighlightTimeout;if(this._highlightedLine)
+this._codeMirror.removeLineClass(this._highlightedLine,null,"cm-highlight");delete this._highlightedLine;},elementsToRestoreScrollPositionsFor:function()
+{return[];},inheritScrollPositions:function(textEditor)
+{},_updatePaddingBottom:function(width,height)
+{var scrollInfo=this._codeMirror.getScrollInfo();var newPaddingBottom;var linesElement=this.element.firstChild.querySelector(".CodeMirror-lines");var lineCount=this._codeMirror.lineCount();if(lineCount<=1)
+newPaddingBottom=0;else
+newPaddingBottom=Math.max(scrollInfo.clientHeight-this._codeMirror.getLineHandle(this._codeMirror.lastLine()).height,0);newPaddingBottom+="px";linesElement.style.paddingBottom=newPaddingBottom;this._codeMirror.setSize(width,height);},_resizeEditor:function()
+{var parentElement=this.element.parentElement;if(!parentElement||!this.isShowing())
+return;var scrollInfo=this._codeMirror.getScrollInfo();var width=parentElement.offsetWidth;var height=parentElement.offsetHeight;this._codeMirror.setSize(width,height);this._updatePaddingBottom(width,height);this._codeMirror.scrollTo(scrollInfo.left,scrollInfo.top);},onResize:function()
+{this._resizeEditor();},editRange:function(range,text)
+{var pos=this._toPos(range);this._codeMirror.replaceRange(text,pos.start,pos.end);var newRange=this._toRange(pos.start,this._codeMirror.posFromIndex(this._codeMirror.indexFromPos(pos.start)+text.length));this._delegate.onTextChanged(range,newRange);if(WebInspector.settings.textEditorAutoDetectIndent.get())
+this._updateEditorIndentation();return newRange;},_wordRangeForCursorPosition:function(lineNumber,column,prefixOnly)
+{var line=this.line(lineNumber);if(column===0||!WebInspector.TextUtils.isWordChar(line.charAt(column-1)))
+return null;var wordStart=column-1;while(wordStart>0&&WebInspector.TextUtils.isWordChar(line.charAt(wordStart-1)))
+--wordStart;if(prefixOnly)
+return new WebInspector.TextRange(lineNumber,wordStart,lineNumber,column);var wordEnd=column;while(wordEnd<line.length&&WebInspector.TextUtils.isWordChar(line.charAt(wordEnd)))
+++wordEnd;return new WebInspector.TextRange(lineNumber,wordStart,lineNumber,wordEnd);},_beforeChange:function(codeMirror,changeObject)
+{if(!this._dictionary)
+return;this._updatedLines=this._updatedLines||{};for(var i=changeObject.from.line;i<=changeObject.to.line;++i)
+this._updatedLines[i]=this.line(i);},_change:function(codeMirror,changeObject)
+{var hasOneLine=this._codeMirror.lineCount()===1;if(hasOneLine!==this._hasOneLine)
+this._resizeEditor();this._hasOneLine=hasOneLine;var widgets=this._elementToWidget.values();for(var i=0;i<widgets.length;++i)
+this._codeMirror.removeLineWidget(widgets[i]);this._elementToWidget.clear();if(this._updatedLines){for(var lineNumber in this._updatedLines)
+this._removeTextFromCompletionDictionary(this._updatedLines[lineNumber]);delete this._updatedLines;}
+var linesToUpdate={};var singleCharInput=false;do{var oldRange=this._toRange(changeObject.from,changeObject.to);var newRange=oldRange.clone();var linesAdded=changeObject.text.length;singleCharInput=(changeObject.origin==="+input"&&changeObject.text.length===1&&changeObject.text[0].length===1)||(changeObject.origin==="+delete"&&changeObject.removed.length===1&&changeObject.removed[0].length===1);if(linesAdded===0){newRange.endLine=newRange.startLine;newRange.endColumn=newRange.startColumn;}else if(linesAdded===1){newRange.endLine=newRange.startLine;newRange.endColumn=newRange.startColumn+changeObject.text[0].length;}else{newRange.endLine=newRange.startLine+linesAdded-1;newRange.endColumn=changeObject.text[linesAdded-1].length;}
+if(!this._muteTextChangedEvent)
+this._delegate.onTextChanged(oldRange,newRange);for(var i=newRange.startLine;i<=newRange.endLine;++i){linesToUpdate[i]=true;}
+if(this._dictionary){for(var i=newRange.startLine;i<=newRange.endLine;++i)
+linesToUpdate[i]=this.line(i);}}while(changeObject=changeObject.next);if(this._dictionary){for(var lineNumber in linesToUpdate)
+this._addTextToCompletionDictionary(linesToUpdate[lineNumber]);}
+if(singleCharInput)
+this._autocompleteController.autocomplete();},_cursorActivity:function()
+{var start=this._codeMirror.getCursor("anchor");var end=this._codeMirror.getCursor("head");this._delegate.selectionChanged(this._toRange(start,end));if(!this._tokenHighlighter.highlightedRegex())
+this._codeMirror.operation(this._tokenHighlighter.highlightSelectedTokens.bind(this._tokenHighlighter));},_scroll:function()
+{if(this._scrollTimer)
+clearTimeout(this._scrollTimer);var topmostLineNumber=this._codeMirror.lineAtHeight(this._codeMirror.getScrollInfo().top,"local");this._scrollTimer=setTimeout(this._delegate.scrollChanged.bind(this._delegate,topmostLineNumber),100);},_focus:function()
+{this._delegate.editorFocused();},_blur:function()
+{this._autocompleteController.finishAutocomplete();},scrollToLine:function(lineNumber)
+{var pos=new CodeMirror.Pos(lineNumber,0);var coords=this._codeMirror.charCoords(pos,"local");this._codeMirror.scrollTo(0,coords.top);},firstVisibleLine:function()
+{return this._codeMirror.lineAtHeight(this._codeMirror.getScrollInfo().top,"local");},lastVisibleLine:function()
+{var scrollInfo=this._codeMirror.getScrollInfo();return this._codeMirror.lineAtHeight(scrollInfo.top+scrollInfo.clientHeight,"local");},selection:function()
+{var start=this._codeMirror.getCursor("anchor");var end=this._codeMirror.getCursor("head");return this._toRange(start,end);},lastSelection:function()
+{return this._lastSelection;},setSelection:function(textRange)
+{this._lastSelection=textRange;var pos=this._toPos(textRange);this._codeMirror.setSelection(pos.start,pos.end);},_detectLineSeparator:function(text)
+{this._lineSeparator=text.indexOf("\r\n")>=0?"\r\n":"\n";},setText:function(text)
+{this._muteTextChangedEvent=true;this._codeMirror.setValue(text);this._updateEditorIndentation();if(this._shouldClearHistory){this._codeMirror.clearHistory();this._shouldClearHistory=false;}
+this._detectLineSeparator(text);delete this._muteTextChangedEvent;},text:function()
+{return this._codeMirror.getValue().replace(/\n/g,this._lineSeparator);},range:function()
+{var lineCount=this.linesCount;var lastLine=this._codeMirror.getLine(lineCount-1);return this._toRange(new CodeMirror.Pos(0,0),new CodeMirror.Pos(lineCount-1,lastLine.length));},line:function(lineNumber)
+{return this._codeMirror.getLine(lineNumber);},get linesCount()
+{return this._codeMirror.lineCount();},setAttribute:function(line,name,value)
+{if(line<0||line>=this._codeMirror.lineCount())
+return;var handle=this._codeMirror.getLineHandle(line);if(handle.attributes===undefined)handle.attributes={};handle.attributes[name]=value;},getAttribute:function(line,name)
+{if(line<0||line>=this._codeMirror.lineCount())
+return null;var handle=this._codeMirror.getLineHandle(line);return handle.attributes&&handle.attributes[name]!==undefined?handle.attributes[name]:null;},removeAttribute:function(line,name)
+{if(line<0||line>=this._codeMirror.lineCount())
+return;var handle=this._codeMirror.getLineHandle(line);if(handle&&handle.attributes)
+delete handle.attributes[name];},_toPos:function(range)
+{return{start:new CodeMirror.Pos(range.startLine,range.startColumn),end:new CodeMirror.Pos(range.endLine,range.endColumn)}},_toRange:function(start,end)
+{return new WebInspector.TextRange(start.line,start.ch,end.line,end.ch);},__proto__:WebInspector.View.prototype}
+WebInspector.CodeMirrorTextEditor.TokenHighlighter=function(codeMirror)
+{this._codeMirror=codeMirror;}
+WebInspector.CodeMirrorTextEditor.TokenHighlighter.prototype={highlightSearchResults:function(regex,range)
+{var oldRegex=this._highlightRegex;this._highlightRegex=regex;this._highlightRange=range;if(this._searchResultMarker){this._searchResultMarker.clear();delete this._searchResultMarker;}
+if(this._highlightDescriptor&&this._highlightDescriptor.selectionStart)
+this._codeMirror.removeLineClass(this._highlightDescriptor.selectionStart.line,"wrap","cm-line-with-selection");var selectionStart=this._highlightRange?new CodeMirror.Pos(this._highlightRange.startLine,this._highlightRange.startColumn):null;if(selectionStart)
+this._codeMirror.addLineClass(selectionStart.line,"wrap","cm-line-with-selection");if(this._highlightRegex===oldRegex){if(this._highlightDescriptor)
+this._highlightDescriptor.selectionStart=selectionStart;}else{this._removeHighlight();this._setHighlighter(this._searchHighlighter.bind(this,this._highlightRegex,this._highlightRange),selectionStart);}
+if(selectionStart){var pos=WebInspector.CodeMirrorTextEditor.prototype._toPos(this._highlightRange);this._searchResultMarker=this._codeMirror.markText(pos.start,pos.end,{className:"cm-column-with-selection"});}},highlightedRegex:function()
+{return this._highlightRegex;},highlightSelectedTokens:function()
+{delete this._highlightRegex;delete this._highlightRange;if(this._highlightDescriptor&&this._highlightDescriptor.selectionStart)
+this._codeMirror.removeLineClass(this._highlightDescriptor.selectionStart.line,"wrap","cm-line-with-selection");this._removeHighlight();var selectionStart=this._codeMirror.getCursor("start");var selectionEnd=this._codeMirror.getCursor("end");if(selectionStart.line!==selectionEnd.line)
+return;if(selectionStart.ch===selectionEnd.ch)
+return;var selectedText=this._codeMirror.getSelection();if(this._isWord(selectedText,selectionStart.line,selectionStart.ch,selectionEnd.ch)){if(selectionStart)
+this._codeMirror.addLineClass(selectionStart.line,"wrap","cm-line-with-selection")
+this._setHighlighter(this._tokenHighlighter.bind(this,selectedText,selectionStart),selectionStart);}},_isWord:function(selectedText,lineNumber,startColumn,endColumn)
+{var line=this._codeMirror.getLine(lineNumber);var leftBound=startColumn===0||!WebInspector.TextUtils.isWordChar(line.charAt(startColumn-1));var rightBound=endColumn===line.length||!WebInspector.TextUtils.isWordChar(line.charAt(endColumn));return leftBound&&rightBound&&WebInspector.TextUtils.isWord(selectedText);},_removeHighlight:function()
+{if(this._highlightDescriptor){this._codeMirror.removeOverlay(this._highlightDescriptor.overlay);delete this._highlightDescriptor;}},_searchHighlighter:function(regex,range,stream)
+{if(stream.column()===0)
+delete this._searchMatchLength;if(this._searchMatchLength){if(this._searchMatchLength>1){for(var i=0;i<this._searchMatchLength-2;++i)
+stream.next();this._searchMatchLength=1;return"search-highlight";}else{stream.next();delete this._searchMatchLength;return"search-highlight search-highlight-end";}}
+var match=stream.match(regex,false);if(match){stream.next();var matchLength=match[0].length;if(matchLength===1)
+return"search-highlight search-highlight-full";this._searchMatchLength=matchLength;return"search-highlight search-highlight-start";}
+while(!stream.match(regex,false)&&stream.next()){};},_tokenHighlighter:function(token,selectionStart,stream)
+{var tokenFirstChar=token.charAt(0);if(stream.match(token)&&(stream.eol()||!WebInspector.TextUtils.isWordChar(stream.peek())))
+return stream.column()===selectionStart.ch?"token-highlight column-with-selection":"token-highlight";var eatenChar;do{eatenChar=stream.next();}while(eatenChar&&(WebInspector.TextUtils.isWordChar(eatenChar)||stream.peek()!==tokenFirstChar));},_setHighlighter:function(highlighter,selectionStart)
+{var overlayMode={token:highlighter};this._codeMirror.addOverlay(overlayMode);this._highlightDescriptor={overlay:overlayMode,selectionStart:selectionStart};}}
+WebInspector.CodeMirrorTextEditor.BlockIndentController=function(codeMirror)
+{codeMirror.addKeyMap(this);}
+WebInspector.CodeMirrorTextEditor.BlockIndentController.prototype={name:"blockIndentKeymap",Enter:function(codeMirror)
+{if(codeMirror.somethingSelected())
+return CodeMirror.Pass;var cursor=codeMirror.getCursor();if(cursor.ch===0)
+return CodeMirror.Pass;var line=codeMirror.getLine(cursor.line);if(line.substr(cursor.ch-1,2)==="{}"){codeMirror.execCommand("newlineAndIndent");codeMirror.setCursor(cursor);codeMirror.execCommand("newlineAndIndent");codeMirror.execCommand("indentMore");}else if(line.substr(cursor.ch-1,1)==="{"){codeMirror.execCommand("newlineAndIndent");codeMirror.execCommand("indentMore");}else
+return CodeMirror.Pass;},"'}'":function(codeMirror)
+{var cursor=codeMirror.getCursor();var line=codeMirror.getLine(cursor.line);for(var i=0;i<line.length;++i)
+if(!WebInspector.TextUtils.isSpaceChar(line.charAt(i)))
+return CodeMirror.Pass;codeMirror.replaceRange("}",cursor);var matchingBracket=codeMirror.findMatchingBracket();if(!matchingBracket||!matchingBracket.match)
+return;line=codeMirror.getLine(matchingBracket.to.line);var desiredIndentation=0;while(desiredIndentation<line.length&&WebInspector.TextUtils.isSpaceChar(line.charAt(desiredIndentation)))
+++desiredIndentation;codeMirror.replaceRange(line.substr(0,desiredIndentation)+"}",new CodeMirror.Pos(cursor.line,0),new CodeMirror.Pos(cursor.line,cursor.ch+1));}}
+WebInspector.CodeMirrorTextEditor.FixWordMovement=function(codeMirror)
+{function moveLeft(shift,codeMirror)
+{var cursor=codeMirror.getCursor("head");if(cursor.ch!==0||cursor.line===0)
+return CodeMirror.Pass;codeMirror.setExtending(shift);codeMirror.execCommand("goLineUp");codeMirror.execCommand("goLineEnd")
+codeMirror.setExtending(false);}
+function moveRight(shift,codeMirror)
+{var cursor=codeMirror.getCursor("head");var line=codeMirror.getLine(cursor.line);if(cursor.ch!==line.length||cursor.line+1===codeMirror.lineCount())
+return CodeMirror.Pass;codeMirror.setExtending(shift);codeMirror.execCommand("goLineDown");codeMirror.execCommand("goLineStart");codeMirror.setExtending(false);}
+function delWordBack(codeMirror)
+{if(codeMirror.somethingSelected())
+return CodeMirror.Pass;var cursor=codeMirror.getCursor("head");if(cursor.ch===0)
+codeMirror.execCommand("delCharBefore");else
+return CodeMirror.Pass;}
+var modifierKey=WebInspector.isMac()?"Alt":"Ctrl";var leftKey=modifierKey+"-Left";var rightKey=modifierKey+"-Right";var keyMap={};keyMap[leftKey]=moveLeft.bind(this,false);keyMap[rightKey]=moveRight.bind(this,false);keyMap["Shift-"+leftKey]=moveLeft.bind(this,true);keyMap["Shift-"+rightKey]=moveRight.bind(this,true);keyMap[modifierKey+"-Backspace"]=delWordBack.bind(this);codeMirror.addKeyMap(keyMap);}
+WebInspector.CodeMirrorTextEditor.AutocompleteController=function(textEditor,codeMirror)
+{this._textEditor=textEditor;this._codeMirror=codeMirror;this._codeMirror.on("scroll",this._onScroll.bind(this));this._codeMirror.on("cursorActivity",this._onCursorActivity.bind(this));}
+WebInspector.CodeMirrorTextEditor.AutocompleteController.prototype={autocomplete:function()
+{var dictionary=this._textEditor._dictionary;if(!dictionary||this._codeMirror.somethingSelected()){this.finishAutocomplete();return;}
+var cursor=this._codeMirror.getCursor();var substituteRange=this._textEditor._wordRangeForCursorPosition(cursor.line,cursor.ch,false);if(!substituteRange||substituteRange.startColumn===cursor.ch){this.finishAutocomplete();return;}
+var prefixRange=substituteRange.clone();prefixRange.endColumn=cursor.ch;var substituteWord=this._textEditor.copyRange(substituteRange);var hasPrefixInDictionary=dictionary.hasWord(substituteWord);if(hasPrefixInDictionary)
+dictionary.removeWord(substituteWord);var wordsWithPrefix=dictionary.wordsWithPrefix(this._textEditor.copyRange(prefixRange));if(hasPrefixInDictionary)
+dictionary.addWord(substituteWord);function sortSuggestions(a,b)
+{return dictionary.wordCount(b)-dictionary.wordCount(a)||a.length-b.length;}
+wordsWithPrefix.sort(sortSuggestions);if(!this._suggestBox){this._suggestBox=new WebInspector.SuggestBox(this,this._textEditor.element,"generic-suggest",6);this._anchorBox=this._anchorBoxForPosition(cursor.line,cursor.ch);}
+this._suggestBox.updateSuggestions(this._anchorBox,wordsWithPrefix,0,true,this._textEditor.copyRange(prefixRange));this._prefixRange=prefixRange;if(!this._suggestBox.visible())
+this.finishAutocomplete();},finishAutocomplete:function()
+{if(!this._suggestBox)
+return;this._suggestBox.hide();this._suggestBox=null;this._prefixRange=null;this._anchorBox=null;},keyDown:function(e)
+{if(!this._suggestBox)
+return false;if(e.keyCode===WebInspector.KeyboardShortcut.Keys.Esc.code){this.finishAutocomplete();return true;}
+if(e.keyCode===WebInspector.KeyboardShortcut.Keys.Tab.code){this._suggestBox.acceptSuggestion();this.finishAutocomplete();return true;}
+return this._suggestBox.keyPressed(e);},applySuggestion:function(suggestion,isIntermediateSuggestion)
+{this._currentSuggestion=suggestion;},acceptSuggestion:function()
+{if(this._prefixRange.endColumn-this._prefixRange.startColumn!==this._currentSuggestion.length){var pos=this._textEditor._toPos(this._prefixRange);this._codeMirror.replaceRange(this._currentSuggestion,pos.start,pos.end,"+autocomplete");}},_onScroll:function()
+{if(!this._suggestBox)
+return;var cursor=this._codeMirror.getCursor();var scrollInfo=this._codeMirror.getScrollInfo();var topmostLineNumber=this._codeMirror.lineAtHeight(scrollInfo.top,"local");var bottomLine=this._codeMirror.lineAtHeight(scrollInfo.top+scrollInfo.clientHeight,"local");if(cursor.line<topmostLineNumber||cursor.line>bottomLine)
+this.finishAutocomplete();else{this._anchorBox=this._anchorBoxForPosition(cursor.line,cursor.ch);this._suggestBox.setPosition(this._anchorBox);}},_onCursorActivity:function()
+{if(!this._suggestBox)
+return;var cursor=this._codeMirror.getCursor();if(cursor.line!==this._prefixRange.startLine||cursor.ch>this._prefixRange.endColumn||cursor.ch<this._prefixRange.startColumn)
+this.finishAutocomplete();},_anchorBoxForPosition:function(line,column)
+{var metrics=this._textEditor.cursorPositionToCoordinates(line,column);return metrics?new AnchorBox(metrics.x,metrics.y,0,metrics.height):null;},}
« no previous file with comments | « chrome_linux64/resources/inspector/AuditsPanel.js ('k') | chrome_linux64/resources/inspector/ElementsPanel.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698