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&"e!=='\''){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;},} |