Skip to content
Browse files

Update CodeMirror to version 2.24.

  • Loading branch information...
1 parent 527806d commit 40003bbc70eae2737a8cfb5c9221f0b56d38ea7e @ariya committed May 6, 2012
Showing with 169 additions and 91 deletions.
  1. +2 −0 assets/codemirror/codemirror.css
  2. +163 −88 assets/codemirror/codemirror.js
  3. +4 −3 assets/codemirror/javascript.js
View
2 assets/codemirror/codemirror.css
@@ -42,11 +42,13 @@
padding: 0; margin: 0;
white-space: pre;
word-wrap: normal;
+ line-height: inherit;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
+ word-break: normal;
}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;
View
251 assets/codemirror/codemirror.js
@@ -1,4 +1,4 @@
-// CodeMirror version 2.23
+// CodeMirror version 2.24
//
// All functions that need access to the editor's state live inside
// the CodeMirror function. Below that, at the bottom of the file,
@@ -98,7 +98,6 @@ var CodeMirror = (function() {
// Register our event handlers.
connect(scroller, "mousedown", operation(onMouseDown));
connect(scroller, "dblclick", operation(onDoubleClick));
- connect(lineSpace, "dragstart", onDragStart);
connect(lineSpace, "selectstart", e_preventDefault);
// Gecko browsers fire contextmenu *after* opening the menu, at
// which point we can't mess with it anymore. Context menu is
@@ -118,9 +117,16 @@ var CodeMirror = (function() {
connect(input, "focus", onFocus);
connect(input, "blur", onBlur);
- connect(scroller, "dragenter", e_stop);
- connect(scroller, "dragover", e_stop);
- connect(scroller, "drop", operation(onDrop));
+ if (options.dragDrop) {
+ connect(lineSpace, "dragstart", onDragStart);
+ function drag_(e) {
+ if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
+ e_stop(e);
+ }
+ connect(scroller, "dragenter", drag_);
+ connect(scroller, "dragover", drag_);
+ connect(scroller, "drop", operation(onDrop));
+ }
connect(scroller, "paste", function(){focusInput(); fastPoll();});
connect(input, "paste", fastPoll);
connect(input, "cut", operation(function(){
@@ -312,6 +318,7 @@ var CodeMirror = (function() {
},
operation: function(f){return operation(f)();},
+ compoundChange: function(f){return compoundChange(f);},
refresh: function(){
updateDisplay(true);
if (scroller.scrollHeight > lastScrollPos)
@@ -336,7 +343,7 @@ var CodeMirror = (function() {
splitLines(code), top, top);
updateInput = true;
}
- function getValue(code) {
+ function getValue() {
var text = [];
doc.iter(0, doc.size, function(line) { text.push(line.text); });
return text.join("\n");
@@ -385,20 +392,22 @@ var CodeMirror = (function() {
} else { lastClick = {time: now, pos: start}; }
var last = start, going;
- if (dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
+ if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
!posLess(start, sel.from) && !posLess(sel.to, start)) {
// Let the drag handler handle this.
if (webkit) lineSpace.draggable = true;
- var up = connect(document, "mouseup", operation(function(e2) {
+ function dragEnd(e2) {
if (webkit) lineSpace.draggable = false;
draggingText = false;
- up();
+ up(); drop();
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
e_preventDefault(e2);
setCursor(start.line, start.ch, true);
focusInput();
}
- }), true);
+ }
+ var up = connect(document, "mouseup", operation(dragEnd), true);
+ var drop = connect(scroller, "drop", operation(dragEnd), true);
draggingText = true;
// IE's approach to draggable
if (lineSpace.dragDrop) lineSpace.dragDrop();
@@ -447,6 +456,7 @@ var CodeMirror = (function() {
selectWordAt(start);
}
function onDrop(e) {
+ if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
e.preventDefault();
var pos = posFromMouse(e, true), files = e.dataTransfer.files;
if (!pos || options.readOnly) return;
@@ -456,12 +466,12 @@ var CodeMirror = (function() {
reader.onload = function() {
text[i] = reader.result;
if (++read == n) {
- pos = clipPos(pos);
- operation(function() {
+ pos = clipPos(pos);
+ operation(function() {
var end = replaceRange(text.join(""), pos, pos);
setSelectionUser(pos, end);
})();
- }
+ }
};
reader.readAsText(file);
}
@@ -472,12 +482,14 @@ var CodeMirror = (function() {
try {
var text = e.dataTransfer.getData("Text");
if (text) {
- var curFrom = sel.from, curTo = sel.to;
- setSelectionUser(pos, pos);
- if (draggingText) replaceRange("", curFrom, curTo);
- replaceSelection(text);
- focusInput();
- }
+ compoundChange(function() {
+ var curFrom = sel.from, curTo = sel.to;
+ setSelectionUser(pos, pos);
+ if (draggingText) replaceRange("", curFrom, curTo);
+ replaceSelection(text);
+ focusInput();
+ });
+ }
}
catch(e){}
}
@@ -529,15 +541,19 @@ var CodeMirror = (function() {
if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
if (e_prop(e, "metaKey")) name = "Cmd-" + name;
+ var stopped = false;
+ function stop() { stopped = true; }
+
if (e_prop(e, "shiftKey")) {
handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap,
- function(b) {return doHandleBinding(b, true);})
+ function(b) {return doHandleBinding(b, true);}, stop)
|| lookupKey(name, options.extraKeys, options.keyMap, function(b) {
if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b);
- });
+ }, stop);
} else {
- handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding);
+ handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop);
}
+ if (stopped) handled = false;
if (handled) {
e_preventDefault(e);
if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
@@ -546,7 +562,7 @@ var CodeMirror = (function() {
}
function handleCharBinding(e, ch) {
var handled = lookupKey("'" + ch + "'", options.extraKeys,
- options.keyMap, doHandleBinding);
+ options.keyMap, function(b) { return doHandleBinding(b, true); });
if (handled) e_preventDefault(e);
return handled;
}
@@ -648,7 +664,7 @@ var CodeMirror = (function() {
if (suppressEdits) return;
var recomputeMaxLength = false, maxLineLength = maxLine.length;
if (!options.lineWrapping)
- doc.iter(from.line, to.line, function(line) {
+ doc.iter(from.line, to.line + 1, function(line) {
if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
});
if (from.line != to.line || newText.length > 1) gutterDirty = true;
@@ -696,14 +712,14 @@ var CodeMirror = (function() {
doc.insert(from.line + 1, added);
}
if (options.lineWrapping) {
- var perLine = scroller.clientWidth / charWidth() - 3;
+ var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3);
doc.iter(from.line, from.line + newText.length, function(line) {
if (line.hidden) return;
var guess = Math.ceil(line.text.length / perLine) || 1;
if (guess != line.height) updateLineHeight(line, guess);
});
} else {
- doc.iter(from.line, i + newText.length, function(line) {
+ doc.iter(from.line, from.line + newText.length, function(line) {
var l = line.text;
if (l.length > maxLineLength) {
maxLine = l; maxLineLength = l.length; maxWidth = null;
@@ -874,8 +890,9 @@ var CodeMirror = (function() {
var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
- if (x1 < screenleft + gutterw) {
- if (x1 < 50) x1 = 0;
+ var atLeft = x1 < gutterw + pl + 10;
+ if (x1 < screenleft + gutterw || atLeft) {
+ if (atLeft) x1 = 0;
scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw);
scrolled = true;
}
@@ -890,10 +907,10 @@ var CodeMirror = (function() {
function visibleLines() {
var lh = textHeight(), top = scroller.scrollTop - paddingTop();
- var from_height = Math.max(0, Math.floor(top / lh));
- var to_height = Math.ceil((top + scroller.clientHeight) / lh);
- return {from: lineAtHeight(doc, from_height),
- to: lineAtHeight(doc, to_height)};
+ var fromHeight = Math.max(0, Math.floor(top / lh));
+ var toHeight = Math.ceil((top + scroller.clientHeight) / lh);
+ return {from: lineAtHeight(doc, fromHeight),
+ to: lineAtHeight(doc, toHeight)};
}
// Uses a set of changes plus the current scroll position to
// determine which DOM updates have to be made, and makes the
@@ -924,7 +941,7 @@ var CodeMirror = (function() {
if (range.from >= range.to) intact.splice(i--, 1);
else intactLines += range.to - range.from;
}
- if (intactLines == to - from) return;
+ if (intactLines == to - from && from == showingFrom && to == showingTo) return;
intact.sort(function(a, b) {return a.domStart - b.domStart;});
var th = textHeight(), gutterDisplay = gutter.style.display;
@@ -1108,12 +1125,14 @@ var CodeMirror = (function() {
selectionDiv.style.display = "none";
} else {
var sameLine = fromPos.y == toPos.y, html = "";
+ var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;
+ var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;
function add(left, top, right, height) {
+ var rstyle = quirksMode ? "width: " + (!right ? clientWidth : clientWidth - right - left) + "px"
+ : "right: " + right + "px";
html += '<div class="CodeMirror-selected" style="position: absolute; left: ' + left +
- 'px; top: ' + top + 'px; right: ' + right + 'px; height: ' + height + 'px"></div>';
+ 'px; top: ' + top + 'px; ' + rstyle + '; height: ' + height + 'px"></div>';
}
- var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;
- var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;
if (sel.from.ch && fromPos.y >= 0) {
var right = sameLine ? clientWidth - toPos.x : 0;
add(fromPos.x, fromPos.y, right, th);
@@ -1189,13 +1208,14 @@ var CodeMirror = (function() {
var line = getLine(lNo);
if (!line.hidden) {
var ch = pos.ch;
- if (ch > oldCh || ch > line.text.length) ch = line.text.length;
+ if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length;
return {line: lNo, ch: ch};
}
lNo += dir;
}
}
var line = getLine(pos.line);
+ var toEnd = pos.ch == line.text.length && pos.ch != oldCh;
if (!line.hidden) return pos;
if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);
else return getNonHidden(-1) || getNonHidden(1);
@@ -1355,7 +1375,7 @@ var CodeMirror = (function() {
return (tabCache[w] = {html: str + "</span>", width: w});
}
function themeChanged() {
- scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") +
+ scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") +
options.theme.replace(/(^|\s)\s*/g, " cm-s-");
}
@@ -1506,8 +1526,7 @@ var CodeMirror = (function() {
if (x <= 0) return 0;
var lineObj = getLine(line), text = lineObj.text;
function getX(len) {
- measure.innerHTML = "<pre><span>" + lineObj.getHTML(makeTab, len) + "</span></pre>";
- return measure.firstChild.firstChild.offsetWidth;
+ return measureLine(lineObj, len).left;
}
var from = 0, fromX = 0, to = text.length, toX;
// Guess a suitable upper bound for our search.
@@ -1530,19 +1549,13 @@ var CodeMirror = (function() {
}
}
- var tempId = Math.floor(Math.random() * 0xffffff).toString(16);
+ var tempId = "CodeMirror-temp-" + Math.floor(Math.random() * 0xffffff).toString(16);
function measureLine(line, ch) {
if (ch == 0) return {top: 0, left: 0};
- var extra = "";
- // Include extra text at the end to make sure the measured line is wrapped in the right way.
- if (options.lineWrapping) {
- var end = line.text.indexOf(" ", ch + 6);
- extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0)));
- }
- measure.innerHTML = "<pre>" + line.getHTML(makeTab, ch) +
- '<span id="CodeMirror-temp-' + tempId + '">' + htmlEscape(line.text.charAt(ch) || " ") + "</span>" +
- extra + "</pre>";
- var elt = document.getElementById("CodeMirror-temp-" + tempId);
+ var wbr = options.lineWrapping && ch < line.text.length &&
+ spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));
+ measure.innerHTML = "<pre>" + line.getHTML(makeTab, ch, tempId, wbr) + "</pre>";
+ var elt = document.getElementById(tempId);
var top = elt.offsetTop, left = elt.offsetLeft;
// Older IEs report zero offsets for spans directly after a wrap
if (ie && top == 0 && left == 0) {
@@ -1790,13 +1803,17 @@ var CodeMirror = (function() {
var changed = line.highlight(mode, state, options.tabSize);
if (changed) realChange = true;
line.stateAfter = copyState(mode, state);
+ var done = null;
if (compare) {
- if (hadState && compare(hadState, state)) return true;
- } else {
+ var same = hadState && compare(hadState, state);
+ if (same != Pass) done = !!same;
+ }
+ if (done == null) {
if (changed !== false || !hadState) unchanged = 0;
else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, "")))
- return true;
+ done = true;
}
+ if (done) return true;
++i;
});
if (bail) return;
@@ -1856,6 +1873,11 @@ var CodeMirror = (function() {
};
}
+ function compoundChange(f) {
+ history.startCompound();
+ try { return f(); } finally { history.endCompound(); }
+ }
+
for (var ext in extensions)
if (extensions.propertyIsEnumerable(ext) &&
!instance.propertyIsEnumerable(ext))
@@ -1877,12 +1899,14 @@ var CodeMirror = (function() {
electricChars: true,
autoClearEmptyLines: false,
onKeyEvent: null,
+ onDragEvent: null,
lineWrapping: false,
lineNumbers: false,
gutter: false,
fixedGutter: false,
firstLineNumber: 1,
readOnly: false,
+ dragDrop: true,
onChange: null,
onCursorActivity: null,
onGutterClick: null,
@@ -1906,6 +1930,10 @@ var CodeMirror = (function() {
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) {
@@ -1922,10 +1950,7 @@ var CodeMirror = (function() {
CodeMirror.getMode = function(options, spec) {
var spec = CodeMirror.resolveMode(spec);
var mfactory = modes[spec.name];
- if (!mfactory) {
- if (window.console) console.warn("No mode " + spec.name + " found, falling back to plain text.");
- return CodeMirror.getMode(options, "text/plain");
- }
+ if (!mfactory) return CodeMirror.getMode(options, "text/plain");
return mfactory(options, spec);
};
CodeMirror.listModes = function() {
@@ -2035,12 +2060,15 @@ var CodeMirror = (function() {
if (typeof val == "string") return keyMap[val];
else return val;
}
- function lookupKey(name, extraMap, map, handle) {
+ function lookupKey(name, extraMap, map, handle, stop) {
function lookup(map) {
map = getKeyMap(map);
var found = map[name];
if (found != null && handle(found)) return true;
- if (map.catchall) return handle(map.catchall);
+ if (map.nofallthrough) {
+ if (stop) stop();
+ return true;
+ }
var fallthrough = map.fallthrough;
if (fallthrough == null) return false;
if (Object.prototype.toString.call(fallthrough) != "[object Array]")
@@ -2402,9 +2430,9 @@ var CodeMirror = (function() {
indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
// Produces an HTML fragment for the line, taking selection,
// marking, and highlighting into account.
- getHTML: function(makeTab, endAt) {
+ getHTML: function(makeTab, wrapAt, wrapId, wrapWBR) {
var html = [], first = true, col = 0;
- function span(text, style) {
+ function span_(text, style) {
if (!text) return;
// Work around a bug where, in some compat modes, IE ignores leading spaces
if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
@@ -2432,24 +2460,50 @@ var CodeMirror = (function() {
if (style) html.push('<span class="', style, '">', escaped, "</span>");
else html.push(escaped);
}
+ var span = span_;
+ if (wrapAt != null) {
+ var outPos = 0, open = "<span id=\"" + wrapId + "\">";
+ span = function(text, style) {
+ var l = text.length;
+ if (wrapAt >= outPos && wrapAt < outPos + l) {
+ if (wrapAt > outPos) {
+ span_(text.slice(0, wrapAt - outPos), style);
+ // See comment at the definition of spanAffectsWrapping
+ if (wrapWBR) html.push("<wbr>");
+ }
+ html.push(open);
+ span_(text.slice(wrapAt - outPos), style);
+ html.push("</span>");
+ wrapAt--;
+ outPos += l;
+ } else {
+ outPos += l;
+ span_(text, style);
+ // Output empty wrapper when at end of line
+ if (outPos == wrapAt && outPos == len) html.push(open + "</span>");
+ // Stop outputting HTML when gone sufficiently far beyond measure
+ else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function(){};
+ }
+ }
+ }
+
var st = this.styles, allText = this.text, marked = this.marked;
var len = allText.length;
- if (endAt != null) len = Math.min(endAt, len);
function styleToClass(style) {
if (!style) return null;
return "cm-" + style.replace(/ +/g, " cm-");
}
- if (!allText && endAt == null)
+ if (!allText && wrapAt == null) {
span(" ");
- else if (!marked || !marked.length)
+ } else if (!marked || !marked.length) {
for (var i = 0, ch = 0; ch < len; i+=2) {
var str = st[i], style = st[i+1], l = str.length;
if (ch + l > len) str = str.slice(0, len - ch);
ch += l;
span(str, styleToClass(style));
}
- else {
+ } else {
var pos = 0, i = 0, text = "", style, sg = 0;
var nextChange = marked[0].from || 0, marks = [], markpos = 0;
function advanceMarks() {
@@ -2535,7 +2589,11 @@ var CodeMirror = (function() {
},
insertHeight: function(at, lines, height) {
this.height += height;
- this.lines.splice.apply(this.lines, [at, 0].concat(lines));
+ // The trick below is apparently too advanced for IE, which
+ // occasionally corrupts this.lines (duplicating elements) when
+ // it is used.
+ if (ie) this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
+ else this.lines.splice.apply(this.lines, [at, 0].concat(lines));
for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
},
iterN: function(at, n, op) {
@@ -2701,33 +2759,36 @@ var CodeMirror = (function() {
function History() {
this.time = 0;
this.done = []; this.undone = [];
+ this.compound = 0;
+ this.closed = false;
}
History.prototype = {
addChange: function(start, added, old) {
this.undone.length = 0;
var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];
var dtime = time - this.time;
- if (dtime > 400 || !last) {
- this.done.push([{start: start, added: added, old: old}]);
- } else if (last.start > start + old.length || last.start + last.added < start - last.added + last.old.length) {
+
+ if (this.compound && cur && !this.closed) {
cur.push({start: start, added: added, old: old});
+ } else if (dtime > 400 || !last || this.closed ||
+ last.start > start + old.length || last.start + last.added < start) {
+ this.done.push([{start: start, added: added, old: old}]);
+ this.closed = false;
} else {
- var oldoff = 0;
- if (start < last.start) {
- for (var i = last.start - start - 1; i >= 0; --i)
- last.old.unshift(old[i]);
- oldoff = Math.min(0, added - old.length);
- last.added += last.start - start + oldoff;
- last.start = start;
- } else if (last.start < start) {
- oldoff = start - last.start;
- added += oldoff;
- }
- for (var i = last.added - oldoff, e = old.length; i < e; ++i)
- last.old.push(old[i]);
- if (last.added < added) last.added = added;
+ var startBefore = Math.max(0, last.start - start),
+ endAfter = Math.max(0, (start + old.length) - (last.start + last.added));
+ for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);
+ for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);
+ if (startBefore) last.start = start;
+ last.added += added - (old.length - startBefore - endAfter);
}
this.time = time;
+ },
+ startCompound: function() {
+ if (!this.compound++) this.closed = true;
+ },
+ endCompound: function() {
+ if (!--this.compound) this.closed = true;
}
};
@@ -2789,8 +2850,10 @@ var CodeMirror = (function() {
var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
var ie = /MSIE \d/.test(navigator.userAgent);
var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
+ var quirksMode = ie && document.documentMode == 5;
var webkit = /WebKit\//.test(navigator.userAgent);
var chrome = /Chrome\//.test(navigator.userAgent);
+ var safari = /Apple Computer/.test(navigator.vendor);
var khtml = /KHTML\//.test(navigator.userAgent);
// Detect drag-and-drop
@@ -2802,13 +2865,25 @@ var CodeMirror = (function() {
return "draggable" in div || "dragDrop" in div;
}();
- var lineSep = "\n";
// Feature-detect whether newlines in textareas are converted to \r\n
- (function () {
+ var lineSep = function () {
var te = document.createElement("textarea");
te.value = "foo\nbar";
- if (te.value.indexOf("\r") > -1) lineSep = "\r\n";
- }());
+ if (te.value.indexOf("\r") > -1) return "\r\n";
+ return "\n";
+ }();
+
+ // 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) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
+ else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/;
// Counts the column offset in a string, taking tabs into account.
// Used mostly to find indentation.
View
7 assets/codemirror/javascript.js
@@ -243,7 +243,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function maybeoperator(type, value) {
if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
- if (type == "operator") return cont(expression);
+ if (type == "operator" || type == ":") return cont(expression);
if (type == ";") return;
if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
if (type == ".") return cont(property, maybeoperator);
@@ -341,8 +341,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
indent: function(state, textAfter) {
if (state.tokenize != jsTokenBase) return 0;
- var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
- type = lexical.type, closing = firstChar == type;
+ 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 + 4;
else if (type == "form" && firstChar == "{") return lexical.indented;
else if (type == "stat" || type == "form") return lexical.indented + indentUnit;

0 comments on commit 40003bb

Please sign in to comment.
Something went wrong with that request. Please try again.