118 changes: 59 additions & 59 deletions addon/lint/javascript-lint.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
var bogus = [ "Dangerous comment" ];

var warnings = [ [ "Expected '{'",
"Statement body should be inside '{ }' braces." ] ];
"Statement body should be inside '{ }' braces." ] ];

var errors = [ "Missing semicolon", "Extra comma", "Missing property name",
"Unmatched ", " and instead saw", " is not defined",
"Unclosed string", "Stopping, unable to continue" ];
"Unmatched ", " and instead saw", " is not defined",
"Unclosed string", "Stopping, unable to continue" ];

function validator(options, text) {
JSHINT(text, options);
Expand Down Expand Up @@ -42,10 +42,10 @@
found = description.indexOf(find) !== -1;

if (force || found) {
error.severity = severity;
error.severity = severity;
}
if (found && replace) {
error.description = replace;
error.description = replace;
}
}
}
Expand All @@ -54,7 +54,7 @@
var description = error.description;
for ( var i = 0; i < bogus.length; i++) {
if (description.indexOf(bogus[i]) !== -1) {
return true;
return true;
}
}
return false;
Expand All @@ -64,59 +64,59 @@
for ( var i = 0; i < errors.length; i++) {
var error = errors[i];
if (error) {
var linetabpositions, index;

linetabpositions = [];

// This next block is to fix a problem in jshint. Jshint
// replaces
// all tabs with spaces then performs some checks. The error
// positions (character/space) are then reported incorrectly,
// not taking the replacement step into account. Here we look
// at the evidence line and try to adjust the character position
// to the correct value.
if (error.evidence) {
// Tab positions are computed once per line and cached
var tabpositions = linetabpositions[error.line];
if (!tabpositions) {
var evidence = error.evidence;
tabpositions = [];
// ugggh phantomjs does not like this
// forEachChar(evidence, function(item, index) {
Array.prototype.forEach.call(evidence, function(item,
index) {
if (item === '\t') {
// First col is 1 (not 0) to match error
// positions
tabpositions.push(index + 1);
}
});
linetabpositions[error.line] = tabpositions;
}
if (tabpositions.length > 0) {
var pos = error.character;
tabpositions.forEach(function(tabposition) {
if (pos > tabposition) pos -= 1;
});
error.character = pos;
}
}

var start = error.character - 1, end = start + 1;
if (error.evidence) {
index = error.evidence.substring(start).search(/.\b/);
if (index > -1) {
end += index;
}
}

// Convert to format expected by validation service
error.description = error.reason;// + "(jshint)";
error.start = error.character;
error.end = end;
error = cleanup(error);

if (error)
var linetabpositions, index;

linetabpositions = [];

// This next block is to fix a problem in jshint. Jshint
// replaces
// all tabs with spaces then performs some checks. The error
// positions (character/space) are then reported incorrectly,
// not taking the replacement step into account. Here we look
// at the evidence line and try to adjust the character position
// to the correct value.
if (error.evidence) {
// Tab positions are computed once per line and cached
var tabpositions = linetabpositions[error.line];
if (!tabpositions) {
var evidence = error.evidence;
tabpositions = [];
// ugggh phantomjs does not like this
// forEachChar(evidence, function(item, index) {
Array.prototype.forEach.call(evidence, function(item,
index) {
if (item === '\t') {
// First col is 1 (not 0) to match error
// positions
tabpositions.push(index + 1);
}
});
linetabpositions[error.line] = tabpositions;
}
if (tabpositions.length > 0) {
var pos = error.character;
tabpositions.forEach(function(tabposition) {
if (pos > tabposition) pos -= 1;
});
error.character = pos;
}
}

var start = error.character - 1, end = start + 1;
if (error.evidence) {
index = error.evidence.substring(start).search(/.\b/);
if (index > -1) {
end += index;
}
}

// Convert to format expected by validation service
error.description = error.reason;// + "(jshint)";
error.start = error.character;
error.end = end;
error = cleanup(error);

if (error)
output.push({message: error.description,
severity: error.severity,
from: CodeMirror.Pos(error.line - 1, start),
Expand Down
58 changes: 36 additions & 22 deletions addon/lint/lint.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ CodeMirror.validate = (function() {

function position(e) {
if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
tt.style.top = (e.clientY - tt.offsetHeight - 5) + "px";
tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px";
tt.style.left = (e.clientX + 5) + "px";
}
CodeMirror.on(document, "mousemove", position);
position(e);
tt.style.opacity = 1;
if (tt.style.opacity != null) tt.style.opacity = 1;
return tt;
}
function rm(elt) {
Expand All @@ -28,6 +28,22 @@ CodeMirror.validate = (function() {
setTimeout(function() { rm(tt); }, 600);
}

function showTooltipFor(e, content, node) {
var tooltip = showTooltip(e, content);
function hide() {
CodeMirror.off(node, "mouseout", hide);
if (tooltip) { hideTooltip(tooltip); tooltip = null; }
}
var poll = setInterval(function() {
if (tooltip) for (var n = node;; n = n.parentNode) {
if (n == document.body) return;
if (!n) { hide(); break; }
}
if (!tooltip) return clearInterval(poll);
}, 400);
CodeMirror.on(node, "mouseout", hide);
}

function LintState(cm, options, hasGutter) {
this.marked = [];
this.options = options;
Expand All @@ -50,17 +66,17 @@ CodeMirror.validate = (function() {
state.marked.length = 0;
}

function makeMarker(labels, severity, multiple) {
function makeMarker(labels, severity, multiple, tooltips) {
var marker = document.createElement("div"), inner = marker;
marker.className = "CodeMirror-lint-marker-" + severity;
if (multiple) {
inner = marker.appendChild(document.createElement("div"));
inner.className = "CodeMirror-lint-marker-multiple";
}

var tooltip;
CodeMirror.on(inner, "mouseover", function(e) { tooltip = showTooltip(e, labels); });
CodeMirror.on(inner, "mouseout", function() { if (tooltip) hideTooltip(tooltip); });
if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
showTooltipFor(e, labels, inner);
});

return marker;
}
Expand Down Expand Up @@ -89,13 +105,13 @@ CodeMirror.validate = (function() {
}

function startLinting(cm) {
var state = cm._lintState, options = state.options;
if (options.async)
options.getAnnotations(cm, updateLinting, options);
else
updateLinting(cm, options.getAnnotations(cm.getValue()));
var state = cm._lintState, options = state.options;
if (options.async)
options.getAnnotations(cm, updateLinting, options);
else
updateLinting(cm, options.getAnnotations(cm.getValue()));
}

function updateLinting(cm, annotationsNotSorted) {
clearMarks(cm);
var state = cm._lintState, options = state.options;
Expand All @@ -115,7 +131,7 @@ CodeMirror.validate = (function() {
if (!SEVERITIES.test(severity)) severity = "error";
maxSeverity = getMaxSeverity(maxSeverity, severity);

if (options.formatAnnotation) ann = options.formatAnnotation(ann);
if (options.formatAnnotation) ann = options.formatAnnotation(ann);
if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));

if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
Expand All @@ -125,7 +141,8 @@ CodeMirror.validate = (function() {
}

if (state.hasGutter)
cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1));
cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1,
state.options.tooltips));
}
if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
}
Expand All @@ -137,13 +154,8 @@ CodeMirror.validate = (function() {
}

function popupSpanTooltip(ann, e) {
var tooltip = showTooltip(e, annotationTooltip(ann));
var target = e.target || e.srcElement;
CodeMirror.on(target, "mouseout", hide);
function hide() {
CodeMirror.off(target, "mouseout", hide);
hideTooltip(tooltip);
}
showTooltipFor(e, annotationTooltip(ann), target);
}

// When the mouseover fires, the cursor might not actually be over
Expand All @@ -170,13 +182,15 @@ CodeMirror.validate = (function() {
CodeMirror.off(cm.getWrapperElement(), "mouseover", cm._lintState.onMouseOver);
delete cm._lintState;
}

if (val) {
var gutters = cm.getOption("gutters"), hasLintGutter = false;
for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
var state = cm._lintState = new LintState(cm, parseOptions(val), hasLintGutter);
cm.on("change", onChange);
CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
if (state.options.tooltips != false)
CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);

startLinting(cm);
}
});
Expand Down
4 changes: 2 additions & 2 deletions addon/mode/multiplex.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
return innerToken;
}
},

indent: function(state, textAfter) {
var mode = state.innerActive ? state.innerActive.mode : outer;
if (!mode.indent) return CodeMirror.Pass;
Expand All @@ -81,7 +81,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
}
}
} else if (mode.close === "\n") {
} else if (state.innerActive.close === "\n") {
state.innerActive = state.inner = null;
}
},
Expand Down
4 changes: 2 additions & 2 deletions addon/mode/overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, comb
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);
Expand Down
2 changes: 1 addition & 1 deletion addon/search/match-highlighter.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
(function() {
var DEFAULT_MIN_CHARS = 2;
var DEFAULT_TOKEN_STYLE = "matchhighlight";

function State(options) {
this.minChars = typeof options == "object" && options.minChars || DEFAULT_MIN_CHARS;
this.style = typeof options == "object" && options.style || DEFAULT_TOKEN_STYLE;
Expand Down
29 changes: 16 additions & 13 deletions addon/search/searchcursor.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
(function(){
var Pos = CodeMirror.Pos;

function SearchCursor(cm, query, pos, caseFold) {
this.atOccurrence = false; this.cm = cm;
function SearchCursor(doc, query, pos, caseFold) {
this.atOccurrence = false; this.doc = doc;
if (caseFold == null && typeof query == "string") caseFold = false;

pos = pos ? cm.clipPos(pos) : Pos(0, 0);
pos = pos ? doc.clipPos(pos) : Pos(0, 0);
this.pos = {from: pos, to: pos};

// The matches method is filled in based on the type of query.
Expand All @@ -17,7 +17,7 @@
this.matches = function(reverse, pos) {
if (reverse) {
query.lastIndex = 0;
var line = cm.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
for (;;) {
query.lastIndex = cutOff;
var newMatch = query.exec(line);
Expand All @@ -28,7 +28,7 @@
}
} else {
query.lastIndex = pos.ch;
var line = cm.getLine(pos.line), match = query.exec(line),
var line = doc.getLine(pos.line), match = query.exec(line),
start = match && match.index;
}
if (match && match[0])
Expand All @@ -48,7 +48,7 @@
this.matches = function() {};
} else {
this.matches = function(reverse, pos) {
var line = fold(cm.getLine(pos.line)), len = query.length, match;
var line = fold(doc.getLine(pos.line)), len = query.length, match;
if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
: (match = line.indexOf(query, pos.ch)) != -1)
return {from: Pos(pos.line, match),
Expand All @@ -57,14 +57,14 @@
}
} else {
this.matches = function(reverse, pos) {
var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln));
var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(doc.getLine(ln));
var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
if (reverse ? offsetA >= pos.ch || offsetA != match.length
: offsetA <= pos.ch || offsetA != line.length - match.length)
return;
for (;;) {
if (reverse ? !ln : ln == cm.lineCount() - 1) return;
line = fold(cm.getLine(ln += reverse ? -1 : 1));
if (reverse ? !ln : ln == doc.lineCount() - 1) return;
line = fold(doc.getLine(ln += reverse ? -1 : 1));
match = target[reverse ? --idx : ++idx];
if (idx > 0 && idx < target.length - 1) {
if (line != match) return;
Expand All @@ -86,7 +86,7 @@
findPrevious: function() {return this.find(true);},

find: function(reverse) {
var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to);
var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
function savePosAndFail(line) {
var pos = Pos(line, 0);
self.pos = {from: pos, to: pos};
Expand All @@ -102,10 +102,10 @@
}
if (reverse) {
if (!pos.line) return savePosAndFail(0);
pos = Pos(pos.line-1, this.cm.getLine(pos.line-1).length);
pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length);
}
else {
var maxLine = this.cm.lineCount();
var maxLine = this.doc.lineCount();
if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
pos = Pos(pos.line + 1, 0);
}
Expand All @@ -118,13 +118,16 @@
replace: function(newText) {
if (!this.atOccurrence) return;
var lines = CodeMirror.splitLines(newText);
this.cm.replaceRange(lines, this.pos.from, this.pos.to);
this.doc.replaceRange(lines, this.pos.from, this.pos.to);
this.pos.to = Pos(this.pos.from.line + lines.length - 1,
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
}
};

CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
return new SearchCursor(this.doc, query, pos, caseFold);
});
CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
return new SearchCursor(this, query, pos, caseFold);
});
})();
2 changes: 1 addition & 1 deletion addon/selection/active-line.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
delete cm._activeLine;
}
});

function clearActiveLine(cm) {
if ("_activeLine" in cm) {
cm.removeLineClass(cm._activeLine, "wrap", WRAP_CLASS);
Expand Down
11 changes: 11 additions & 0 deletions bin/lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env node

var lint = require("../test/lint/lint");

process.chdir(__dirname.slice(0, __dirname.lastIndexOf("/")));

lint.checkDir("mode");
lint.checkDir("lib");
lint.checkDir("addon");

process.exit(lint.success() ? 0 : 1);
2 changes: 2 additions & 0 deletions demo/theme.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<link rel="stylesheet" href="../theme/vibrant-ink.css">
<link rel="stylesheet" href="../theme/solarized.css">
<link rel="stylesheet" href="../theme/twilight.css">
<link rel="stylesheet" href="../theme/midnight.css">
<script src="../mode/javascript/javascript.js"></script>
<link rel="stylesheet" href="../doc/docs.css">

Expand Down Expand Up @@ -54,6 +55,7 @@ <h1>CodeMirror: Theme demo</h1>
<option>elegant</option>
<option>erlang-dark</option>
<option>lesser-dark</option>
<option>midnight</option>
<option>monokai</option>
<option>neat</option>
<option>night</option>
Expand Down
5 changes: 4 additions & 1 deletion doc/compress.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<input type="hidden" id="download" name="download" value="codemirror-compressed.js"/>
<p>Version: <select id="version" onchange="setVersion(this);" style="padding: 1px">
<option value="http://codemirror.net/">HEAD</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.12;f=">3.12</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.11;f=">3.11</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.1;f=">3.1</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=v3.02;f=">3.02</option>
Expand Down Expand Up @@ -80,6 +81,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<option value="http://codemirror.net/mode/ecl/ecl.js">ecl.js</option>
<option value="http://codemirror.net/mode/erlang/erlang.js">erlang.js</option>
<option value="http://codemirror.net/mode/gfm/gfm.js">gfm.js</option>
<option value="http://codemirror.net/mode/gas/gas.js">gas.js</option>
<option value="http://codemirror.net/mode/go/go.js">go.js</option>
<option value="http://codemirror.net/mode/groovy/groovy.js">groovy.js</option>
<option value="http://codemirror.net/mode/haskell/haskell.js">haskell.js</option>
Expand Down Expand Up @@ -143,6 +145,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<option value="http://codemirror.net/addon/fold/xml-fold.js">xml-fold.js</option>
<option value="http://codemirror.net/addon/fold/brace-fold.js">brace-fold.js</option>
<option value="http://codemirror.net/addon/fold/indent-fold.js">indent-fold.js</option>
<option value="http://codemirror.net/addon/hint/show-hint.js">show-hint.js</option>
<option value="http://codemirror.net/addon/hint/javascript-hint.js">javascript-hint.js</option>
<option value="http://codemirror.net/addon/hint/xml-hint.js">xml-hint.js</option>
<option value="http://codemirror.net/addon/hint/html-hint.js">html-hint.js</option>
Expand All @@ -168,7 +171,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<option value="http://codemirror.net/keymap/emacs.js">emacs.js</option>
<option value="http://codemirror.net/keymap/vim.js">vim.js</option>
</optgroup>
</select></p>
</select>

<p>
<button type="submit">Compress</button> with <a href="http://github.com/mishoo/UglifyJS/">UglifyJS</a>
Expand Down
2 changes: 1 addition & 1 deletion doc/internals.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
integrated into about a thousand systems by now. The most prominent
one, since a few weeks,
being <a href="http://googlecode.blogspot.com/2011/01/make-quick-fixes-quicker-on-google.html">Google
code's project hosting</a>. It works, and it's being used widely.</a>
code's project hosting</a>. It works, and it's being used widely.</p>

<p>Still, I did not start replacing it because I was bored. CodeMirror
1 was heavily reliant on <code>designMode</code>
Expand Down
564 changes: 310 additions & 254 deletions doc/manual.html

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions doc/modes.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="../mode/diff/index.html">diff</a></li>
<li><a href="../mode/ecl/index.html">ECL</a></li>
<li><a href="../mode/erlang/index.html">Erlang</a></li>
<li><a href="../mode/gas/index.html">Gas</a> (AT&amp;T-style assembly)</li>
<li><a href="../mode/go/index.html">Go</a></li>
<li><a href="../mode/groovy/index.html">Groovy</a></li>
<li><a href="../mode/haskell/index.html">Haskell</a></li>
Expand Down
4 changes: 2 additions & 2 deletions doc/oldrelease.html
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
faster, smaller, simpler to use, and less dependent on browser
quirks. See <a href="internals.html">this</a>
and <a href="http://groups.google.com/group/codemirror/browse_thread/thread/5a8e894024a9f580">this</a>
for more information.</a>
for more information.</p>

<p class="rel">28-03-2011: <a href="http://codemirror.net/codemirror-1.0.zip">Version 1.0</a>:</p>
<ul class="rel-note">
Expand All @@ -345,7 +345,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
</ul>

<p class="rel">22-02-2011: <a href="https://github.com/marijnh/codemirror/tree/beta2">Version 2.0 beta 2</a>:</p>
<p class="rel-note">Somewhat more mature API, lots of bugs shaken out.</a>
<p class="rel-note">Somewhat more mature API, lots of bugs shaken out.</p>

<p class="rel">17-02-2011: <a href="http://codemirror.net/codemirror-0.94.zip">Version 0.94</a>:</p>
<ul class="rel-note">
Expand Down
4 changes: 4 additions & 0 deletions doc/realworld.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="http://brackets.io">Adobe Brackets</a> (code editor)</li>
<li><a href="http://amber-lang.net/">Amber</a> (JavaScript-based Smalltalk system)</li>
<li><a href="http://apeye.org/">APEye</a> (tool for testing &amp; documenting APIs)</li>
<li><a href="http://buzz.blogger.com/2013/04/improvements-to-blogger-template-html.html">Blogger's template editor</a></li>
<li><a href="http://bluegriffon.org/">BlueGriffon</a> (HTML editor)</li>
<li><a href="http://cargocollective.com/">Cargo Collective</a> (creative publishing platform)</li>
<li><a href="http://drupal.org/project/cpn">Code per Node</a> (Drupal module)</li>
<li><a href="http://www.codebugapp.com/">Codebug</a> (PHP Xdebug front-end)</li>
<li><a href="http://emmet.io/blog/codemirror-movie/">CodeMirror movie</a> (scripted editing demos)</li>
<li><a href="http://code.google.com/p/codemirror2-gwt/">CodeMirror2-GWT</a> (Google Web Toolkit wrapper)</li>
Expand All @@ -47,6 +49,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="http://www.fastfig.com/">Fastfig</a> (online computation/math tool)</li>
<li><a href="https://metacpan.org/module/Farabi">Farabi</a> (modern Perl IDE)</li>
<li><a href="http://blog.pamelafox.org/2012/02/interactive-html5-slides-with-fathomjs.html">FathomJS integration</a> (slides with editors, again)</li>
<li><a href="http://www.firepad.io">Firepad</a> (collaborative text editor)</li>
<li><a href="http://tour.golang.org">Go language tour</a></li>
<li><a href="https://github.com/github/android">GitHub's Android app</a></li>
<li><a href="https://script.google.com/">Google Apps Script</a></li>
Expand Down Expand Up @@ -90,6 +93,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="http://www.wescheme.org/">WeScheme</a> (learning tool)</li>
<li><a href="http://wordpress.org/extend/plugins/codemirror-for-codeeditor/">WordPress plugin</a></li>
<li><a href="http://www.xosystem.org/home/applications_websites/xosystem_website/xoside_EN.php">XOSide</a> (online editor)</li>
<li><a href="http://videlibri.sourceforge.net/cgi-bin/xidelcgi">XQuery tester</a></li>
</ul>

</body>
Expand Down
19 changes: 17 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,9 @@ <h2>Support CodeMirror</h2>
(<span onclick="document.getElementById('paypal').submit();"
class="quasilink">Paypal</span>,
<span onclick="document.getElementById('bankinfo').style.display = 'block';"
class="quasilink">bank</span>, or
<a href="https://www.gittip.com/marijnh">Gittip</a>)</li>
class="quasilink">bank</span>,
<a href="https://www.gittip.com/marijnh">Gittip</a>, or
<a href="https://flattr.com/profile/marijnh">Flattr</a>)</li>
<li>Purchase <a href="#commercial">commercial support</a></li>
</ul>

Expand All @@ -285,6 +286,20 @@ <h2>Reading material</h2>

<h2 id=releases>Releases</h2>

<p class="rel">19-04-2013: <a href="http://codemirror.net/codemirror-3.12.zip">Version 3.12</a>:</p>

<ul class="rel-note">
<li>New mode: <a href="mode/gas/index.html">GNU assembler</a>.</li>
<li>New
options: <a href="doc/manual.html#option_maxHighlightLength"><code>maxHighlightLength</code></a>
and <a href="doc/manual.html#option_historyEventDelay"><code>historyEventDelay</code></a>.</li>
<li>Added <a href="doc/manual.html#mark_addToHistory"><code>addToHistory</code></a>
option for <code>markText</code>.</li>
<li>Various fixes to JavaScript tokenization and indentation corner cases.</li>
<li>Further improvements to the vim mode.</li>
<li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.11...v3.12">list of patches</a>.</li>
</ul>

<p class="rel">20-03-2013: <a href="http://codemirror.net/codemirror-3.11.zip">Version 3.11</a>:</p>

<ul class="rel-note">
Expand Down
271 changes: 265 additions & 6 deletions keymap/vim.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/codemirror.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}

.CodeMirror-scroll {
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px; padding-right: 30px;
height: 100%;
Expand Down
205 changes: 137 additions & 68 deletions lib/codemirror.js

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions mode/asterisk/asterisk.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Created: 05/17/2012 09:20:25 PM
* Revision: none
*
* Author: Stas Kobzar (stas@modulis.ca),
* Author: Stas Kobzar (stas@modulis.ca),
* Company: Modulis.ca Inc.
*
* =====================================================================================
Expand Down Expand Up @@ -99,9 +99,9 @@ CodeMirror.defineMode("asterisk", function() {
state.extenStart = true;
switch(cur) {
case 'same': state.extenSame = true; break;
case 'include':
case 'switch':
case 'ignorepat':
case 'include':
case 'switch':
case 'ignorepat':
state.extenInclude = true;break;
default:break;
}
Expand All @@ -121,7 +121,7 @@ CodeMirror.defineMode("asterisk", function() {
};
},
token: function(stream, state) {

var cur = '';
var ch = '';
if(stream.eatSpace()) return null;
Expand Down Expand Up @@ -174,7 +174,7 @@ CodeMirror.defineMode("asterisk", function() {
} else{
return basicToken(stream,state);
}

return null;
}
};
Expand Down
28 changes: 14 additions & 14 deletions mode/clike/clike.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
});
CodeMirror.defineMIME("text/x-java", {
name: "clike",
keywords: words("abstract assert boolean break byte case catch char class const continue default " +
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 " +
Expand All @@ -238,12 +238,12 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
});
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" +
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" +
Expand All @@ -265,30 +265,30 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
CodeMirror.defineMIME("text/x-scala", {
name: "clike",
keywords: words(

/* scala */
"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 _ : = => <- <: " +
"<% >: # @ " +

/* package scala */
"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 :: #:: " +
/* package java.lang */

/* package java.lang */
"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"),
Expand Down
9 changes: 4 additions & 5 deletions mode/clojure/clojure.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ CodeMirror.defineMode("clojure", function () {
}

var atoms = makeKeywords("true false nil");

var keywords = makeKeywords(
"defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle");

Expand Down Expand Up @@ -44,8 +44,7 @@ CodeMirror.defineMode("clojure", function () {
sign: /[+-]/,
exponent: /e/i,
keyword_char: /[^\s\(\[\;\)\]]/,
basic: /[\w\$_\-]/,
lang_keyword: /[\w*+!\-_?:\/]/
symbol: /[\w*+!\-\._?:\/]/
};

function stateStack(indent, type, prev) { // represents a state stack object
Expand Down Expand Up @@ -195,10 +194,10 @@ CodeMirror.defineMode("clojure", function () {
popStack(state);
}
} else if ( ch == ":" ) {
stream.eatWhile(tests.lang_keyword);
stream.eatWhile(tests.symbol);
return ATOM;
} else {
stream.eatWhile(tests.basic);
stream.eatWhile(tests.symbol);

if (keywords && keywords.propertyIsEnumerable(stream.current())) {
returnType = KEYWORD;
Expand Down
2 changes: 1 addition & 1 deletion mode/coffeescript/coffeescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ CodeMirror.defineMode('coffeescript', function(conf) {
if (stream.match(identifiers)) {
return 'variable';
}

if (stream.match(properties)) {
return 'property';
}
Expand Down
24 changes: 12 additions & 12 deletions mode/ecl/ecl.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,18 @@ CodeMirror.defineMode("ecl", function(config) {
} else if (builtin.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
return "builtin";
} else { //Data types are of from KEYWORD##
var i = cur.length - 1;
while(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_'))
--i;
if (i > 0) {
var cur2 = cur.substr(0, i + 1);
if (variable_3.propertyIsEnumerable(cur2)) {
if (blockKeywords.propertyIsEnumerable(cur2)) curPunc = "newstatement";
return "variable-3";
}
}
} else { //Data types are of from KEYWORD##
var i = cur.length - 1;
while(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_'))
--i;

if (i > 0) {
var cur2 = cur.substr(0, i + 1);
if (variable_3.propertyIsEnumerable(cur2)) {
if (blockKeywords.propertyIsEnumerable(cur2)) curPunc = "newstatement";
return "variable-3";
}
}
}
if (atoms.propertyIsEnumerable(cur)) return "atom";
return null;
Expand Down
2 changes: 1 addition & 1 deletion mode/erlang/erlang.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ CodeMirror.defineMode("erlang", function(cmCfg) {
return rval(state,stream,"function");
}
}
return rval(state,stream,"atom");
return rval(state,stream,"atom");
}

// number
Expand Down
326 changes: 326 additions & 0 deletions mode/gas/gas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
CodeMirror.defineMode("gas", function(_config, parserConfig) {
'use strict';

// If an architecture is specified, its initialization function may
// populate this array with custom parsing functions which will be
// tried in the event that the standard functions do not find a match.
var custom = [];

// The symbol used to start a line comment changes based on the target
// architecture.
// If no architecture is pased in "parserConfig" then only multiline
// comments will have syntax support.
var lineCommentStartSymbol = "";

// These directives are architecture independent.
// Machine specific directives should go in their respective
// architecture initialization function.
// Reference:
// http://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops
var directives = {
".abort" : "builtin",
".align" : "builtin",
".altmacro" : "builtin",
".ascii" : "builtin",
".asciz" : "builtin",
".balign" : "builtin",
".balignw" : "builtin",
".balignl" : "builtin",
".bundle_align_mode" : "builtin",
".bundle_lock" : "builtin",
".bundle_unlock" : "builtin",
".byte" : "builtin",
".cfi_startproc" : "builtin",
".comm" : "builtin",
".data" : "builtin",
".def" : "builtin",
".desc" : "builtin",
".dim" : "builtin",
".double" : "builtin",
".eject" : "builtin",
".else" : "builtin",
".elseif" : "builtin",
".end" : "builtin",
".endef" : "builtin",
".endfunc" : "builtin",
".endif" : "builtin",
".equ" : "builtin",
".equiv" : "builtin",
".eqv" : "builtin",
".err" : "builtin",
".error" : "builtin",
".exitm" : "builtin",
".extern" : "builtin",
".fail" : "builtin",
".file" : "builtin",
".fill" : "builtin",
".float" : "builtin",
".func" : "builtin",
".global" : "builtin",
".gnu_attribute" : "builtin",
".hidden" : "builtin",
".hword" : "builtin",
".ident" : "builtin",
".if" : "builtin",
".incbin" : "builtin",
".include" : "builtin",
".int" : "builtin",
".internal" : "builtin",
".irp" : "builtin",
".irpc" : "builtin",
".lcomm" : "builtin",
".lflags" : "builtin",
".line" : "builtin",
".linkonce" : "builtin",
".list" : "builtin",
".ln" : "builtin",
".loc" : "builtin",
".loc_mark_labels" : "builtin",
".local" : "builtin",
".long" : "builtin",
".macro" : "builtin",
".mri" : "builtin",
".noaltmacro" : "builtin",
".nolist" : "builtin",
".octa" : "builtin",
".offset" : "builtin",
".org" : "builtin",
".p2align" : "builtin",
".popsection" : "builtin",
".previous" : "builtin",
".print" : "builtin",
".protected" : "builtin",
".psize" : "builtin",
".purgem" : "builtin",
".pushsection" : "builtin",
".quad" : "builtin",
".reloc" : "builtin",
".rept" : "builtin",
".sbttl" : "builtin",
".scl" : "builtin",
".section" : "builtin",
".set" : "builtin",
".short" : "builtin",
".single" : "builtin",
".size" : "builtin",
".skip" : "builtin",
".sleb128" : "builtin",
".space" : "builtin",
".stab" : "builtin",
".string" : "builtin",
".struct" : "builtin",
".subsection" : "builtin",
".symver" : "builtin",
".tag" : "builtin",
".text" : "builtin",
".title" : "builtin",
".type" : "builtin",
".uleb128" : "builtin",
".val" : "builtin",
".version" : "builtin",
".vtable_entry" : "builtin",
".vtable_inherit" : "builtin",
".warning" : "builtin",
".weak" : "builtin",
".weakref" : "builtin",
".word" : "builtin"
};

var registers = {};

function x86(_parserConfig) {
lineCommentStartSymbol = "#";

registers.ax = "variable";
registers.eax = "variable-2";
registers.rax = "variable-3";

registers.bx = "variable";
registers.ebx = "variable-2";
registers.rbx = "variable-3";

registers.cx = "variable";
registers.ecx = "variable-2";
registers.rcx = "variable-3";

registers.dx = "variable";
registers.edx = "variable-2";
registers.rdx = "variable-3";

registers.si = "variable";
registers.esi = "variable-2";
registers.rsi = "variable-3";

registers.di = "variable";
registers.edi = "variable-2";
registers.rdi = "variable-3";

registers.sp = "variable";
registers.esp = "variable-2";
registers.rsp = "variable-3";

registers.bp = "variable";
registers.ebp = "variable-2";
registers.rbp = "variable-3";

registers.ip = "variable";
registers.eip = "variable-2";
registers.rip = "variable-3";

registers.cs = "keyword";
registers.ds = "keyword";
registers.ss = "keyword";
registers.es = "keyword";
registers.fs = "keyword";
registers.gs = "keyword";
}

function armv6(_parserConfig) {
// Reference:
// http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf
// http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf
lineCommentStartSymbol = "@";
directives.syntax = "builtin";

registers.r0 = "variable";
registers.r1 = "variable";
registers.r2 = "variable";
registers.r3 = "variable";
registers.r4 = "variable";
registers.r5 = "variable";
registers.r6 = "variable";
registers.r7 = "variable";
registers.r8 = "variable";
registers.r9 = "variable";
registers.r10 = "variable";
registers.r11 = "variable";
registers.r12 = "variable";

registers.sp = "variable-2";
registers.lr = "variable-2";
registers.pc = "variable-2";
registers.r13 = registers.sp;
registers.r14 = registers.lr;
registers.r15 = registers.pc;

custom.push(function(ch, stream) {
if (ch === '#') {
stream.eatWhile(/\w/);
return "number";
}
});
}

var arch = parserConfig.architecture.toLowerCase();
if (arch === "x86") {
x86(parserConfig);
} else if (arch === "arm" || arch === "armv6") {
armv6(parserConfig);
}

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

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

return {
startState: function() {
return {
tokenize: null
};
},

token: function(stream, state) {
if (state.tokenize) {
return state.tokenize(stream, state);
}

if (stream.eatSpace()) {
return null;
}

var style, cur, ch = stream.next();

if (ch === "/") {
if (stream.eat("*")) {
state.tokenize = clikeComment;
return clikeComment(stream, state);
}
}

if (ch === lineCommentStartSymbol) {
stream.skipToEnd();
return "comment";
}

if (ch === '"') {
nextUntilUnescaped(stream, '"');
return "string";
}

if (ch === '.') {
stream.eatWhile(/\w/);
cur = stream.current().toLowerCase();
style = directives[cur];
return style || null;
}

if (ch === '=') {
stream.eatWhile(/\w/);
return "tag";
}

if (ch === '{') {
return "braket";
}

if (ch === '}') {
return "braket";
}

if (/\d/.test(ch)) {
if (ch === "0" && stream.eat("x")) {
stream.eatWhile(/[0-9a-fA-F]/);
return "number";
}
stream.eatWhile(/\d/);
return "number";
}

if (/\w/.test(ch)) {
stream.eatWhile(/\w/);
if (stream.eat(":")) {
return 'tag';
}
cur = stream.current().toLowerCase();
style = registers[cur];
return style || null;
}

for (var i = 0; i < custom.length; i++) {
style = custom[i](ch, stream, state);
if (style) {
return style;
}
}
}
};
});
57 changes: 57 additions & 0 deletions mode/gas/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CodeMirror: Gas mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="gas.js"></script>
<link rel="stylesheet" href="../../doc/docs.css">
<style>.CodeMirror {border: 2px inset #dee;}</style>
</head>
<body>
<h1>CodeMirror: Gas mode</h1>

<form>
<textarea id="code" name="code">
.syntax unified
.global main

/*
* A
* multi-line
* comment.
*/

@ A single line comment.

main:
push {sp, lr}
ldr r0, =message
bl puts
mov r0, #0
pop {sp, pc}

message:
.asciz "Hello world!<br />"
</textarea>
</form>

<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
mode: {name: "gas", architecture: "ARMv6"},
});
</script>

<p>Handles AT&amp;T assembler syntax (more specifically this handles
the GNU Assembler (gas) syntax.)
It takes a single optional configuration parameter:
<code>architecture</code>, which can be one of <code>"ARM"</code>,
<code>"ARMv6"</code> or <code>"x86"</code>.
Including the parameter adds syntax for the registers and special
directives for the supplied architecture.

<p><strong>MIME types defined:</strong> <code>text/x-gas</code></p>
</body>
</html>
52 changes: 26 additions & 26 deletions mode/haskell/haskell.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ CodeMirror.defineMode("haskell", function() {
setState(f);
return f(source, setState);
}

// These should all be Unicode extended, as per the Haskell 2010 report
var smallRE = /[a-z_]/;
var largeRE = /[A-Z]/;
Expand All @@ -15,12 +15,12 @@ CodeMirror.defineMode("haskell", function() {
var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/;
var specialRE = /[(),;[\]`{}]/;
var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer

function normal(source, setState) {
if (source.eatWhile(whiteCharRE)) {
return null;
}

var ch = source.next();
if (specialRE.test(ch)) {
if (ch == '{' && source.eat('-')) {
Expand All @@ -32,7 +32,7 @@ CodeMirror.defineMode("haskell", function() {
}
return null;
}

if (ch == '\'') {
if (source.eat('\\')) {
source.next(); // should handle other escapes here
Expand All @@ -45,24 +45,24 @@ CodeMirror.defineMode("haskell", function() {
}
return "error";
}

if (ch == '"') {
return switchState(source, setState, stringLiteral);
}

if (largeRE.test(ch)) {
source.eatWhile(idRE);
if (source.eat('.')) {
return "qualifier";
}
return "variable-2";
}

if (smallRE.test(ch)) {
source.eatWhile(idRE);
return "variable";
}

if (digitRE.test(ch)) {
if (ch == '0') {
if (source.eat(/[xX]/)) {
Expand All @@ -87,7 +87,7 @@ CodeMirror.defineMode("haskell", function() {
}
return t;
}

if (symbolRE.test(ch)) {
if (ch == '-' && source.eat(/-/)) {
source.eatWhile(/-/);
Expand All @@ -101,12 +101,12 @@ CodeMirror.defineMode("haskell", function() {
t = "variable-2";
}
source.eatWhile(symbolRE);
return t;
return t;
}

return "error";
}

function ncomment(type, nest) {
if (nest == 0) {
return normal;
Expand All @@ -130,7 +130,7 @@ CodeMirror.defineMode("haskell", function() {
return type;
};
}

function stringLiteral(source, setState) {
while (!source.eol()) {
var ch = source.next();
Expand All @@ -153,7 +153,7 @@ CodeMirror.defineMode("haskell", function() {
setState(normal);
return "error";
}

function stringGap(source, setState) {
if (source.eat('\\')) {
return switchState(source, setState, stringLiteral);
Expand All @@ -162,8 +162,8 @@ CodeMirror.defineMode("haskell", function() {
setState(normal);
return "error";
}


var wellKnownWords = (function() {
var wkw = {};
function setType(t) {
Expand All @@ -172,27 +172,27 @@ CodeMirror.defineMode("haskell", function() {
wkw[arguments[i]] = t;
};
}

setType("keyword")(
"case", "class", "data", "default", "deriving", "do", "else", "foreign",
"if", "import", "in", "infix", "infixl", "infixr", "instance", "let",
"module", "newtype", "of", "then", "type", "where", "_");

setType("keyword")(
"\.\.", ":", "::", "=", "\\", "\"", "<-", "->", "@", "~", "=>");

setType("builtin")(
"!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<",
"==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**");

setType("builtin")(
"Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq",
"False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT",
"IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left",
"Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read",
"ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS",
"String", "True");

setType("builtin")(
"abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf",
"asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling",
Expand Down Expand Up @@ -220,16 +220,16 @@ CodeMirror.defineMode("haskell", function() {
"toRational", "truncate", "uncurry", "undefined", "unlines", "until",
"unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip",
"zip3", "zipWith", "zipWith3");

return wkw;
})();



return {
startState: function () { return { f: normal }; },
copyState: function (s) { return { f: s.f }; },

token: function(stream, state) {
var t = state.f(stream, function(s) { state.f = s; });
var w = stream.current();
Expand Down
30 changes: 15 additions & 15 deletions mode/haxe/haxe.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CodeMirror.defineMode("haxe", function(config, parserConfig) {
var indentUnit = config.indentUnit;

// Tokenizer

var keywords = function(){
Expand All @@ -12,10 +12,10 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
"if": A, "while": A, "else": B, "do": B, "try": B,
"return": C, "break": C, "continue": C, "new": C, "throw": C,
"var": kw("var"), "inline":attribute, "static": attribute, "using":kw("import"),
"public": attribute, "private": attribute, "cast": kw("cast"), "import": kw("import"), "macro": kw("macro"),
"public": attribute, "private": attribute, "cast": kw("cast"), "import": kw("import"), "macro": kw("macro"),
"function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"),
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
"in": operator, "never": kw("property_access"), "trace":kw("trace"),
"in": operator, "never": kw("property_access"), "trace":kw("trace"),
"class": type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type,
"true": atom, "false": atom, "null": atom
};
Expand Down Expand Up @@ -55,14 +55,14 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
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 (state.reAllowed && (ch == "~" && stream.eat(/\//))) {
nextUntilUnescaped(stream, "/");
stream.eatWhile(/[gimsu]/);
stream.eatWhile(/[gimsu]/);
return ret("regexp", "string-2");
}
else if (ch == "/") {
Expand Down Expand Up @@ -146,13 +146,13 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
for (var v = state.localVars; v; v = v.next)
if (v.name == varname) return true;
}

function parseHaxe(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;

Expand All @@ -168,7 +168,7 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
}
}
}

function imported(state, typename)
{
if (/[a-z]/.test(typename.charAt(0)))
Expand All @@ -177,8 +177,8 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
for (var i = 0; i<len; i++)
if(state.importedtypes[i]==typename) return true;
}


function registerimport(importname) {
var state = cx.state;
for (var t = state.importedtypes; t; t = t.next)
Expand Down Expand Up @@ -278,7 +278,7 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
if (type.match(/[;\}\)\],]/)) return pass();
return pass(expression);
}

function maybeoperator(type, value) {
if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
if (type == "operator" || type == ":") return cont(expression);
Expand All @@ -302,17 +302,17 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
function metaargs(type) {
if(type == "variable") return cont();
}

function importdef (type, value) {
if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
else if(type == "variable" || type == "property" || type == ".") return cont(importdef);
}

function typedef (type, value)
{
if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
}

function maybelabel(type) {
if (type == ":") return cont(poplex, statement);
return pass(maybeoperator, expect(";"), poplex);
Expand Down Expand Up @@ -388,7 +388,7 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
cc: [],
lexical: new HaxeLexical((basecolumn || 0) - indentUnit, 0, "block", false),
localVars: parserConfig.localVars,
importedtypes: defaulttypes,
importedtypes: defaulttypes,
context: parserConfig.localVars && {vars: parserConfig.localVars},
indented: 0
};
Expand Down
12 changes: 6 additions & 6 deletions mode/htmlembedded/htmlembedded.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {

//config settings
var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i,
scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i;

//inner modes
var scriptingMode, htmlMixedMode;

//tokenizer when in html mode
function htmlDispatch(stream, state) {
if (stream.match(scriptStartRegex, false)) {
Expand All @@ -32,7 +32,7 @@ CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
startState: function() {
scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec);
htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed");
return {
return {
token : parserConfig.startOpen ? scriptingDispatch : htmlDispatch,
htmlState : CodeMirror.startState(htmlMixedMode),
scriptState : CodeMirror.startState(scriptingMode)
Expand All @@ -49,15 +49,15 @@ CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
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) {
Expand Down
12 changes: 8 additions & 4 deletions mode/javascript/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,14 @@ <h1>CodeMirror: JavaScript mode</h1>
JavaScript mode supports a two configuration
options:
<ul>
<li><code>json</code> which will set the mode to expect JSON data rather than a JavaScript program.</li>
<li>
<code>typescript</code> which will activate additional syntax highlighting and some other things for TypeScript code (<a href="typescript.html">demo</a>).
</li>
<li><code>json</code> which will set the mode to expect JSON
data rather than a JavaScript program.</li>
<li><code>typescript</code> which will activate additional
syntax highlighting and some other things for TypeScript code
(<a href="typescript.html">demo</a>).</li>
<li><code>statementIndent</code> which (given a number) will
determine the amount of indentation to use for statements
continued on a new line.</li>
</ul>
</p>

Expand Down
76 changes: 53 additions & 23 deletions mode/javascript/javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
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,
"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"),
Expand Down Expand Up @@ -87,7 +87,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
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");
Expand Down Expand Up @@ -170,7 +170,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
// 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;

Expand Down Expand Up @@ -256,6 +256,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
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);
Expand All @@ -269,34 +270,45 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return pass(pushlex("stat"), expression, expect(";"), poplex);
}
function expression(type) {
if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
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, maybeoperator);
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
if (type == "operator") return cont(expression);
if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
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 maybeoperator(type, value) {

function maybeoperatorComma(type, value) {
if (type == ",") return cont(expression);
return maybeoperatorNoComma(type, value, maybeoperatorComma);
}
function maybeoperatorNoComma(type, value, me) {
if (!me) me = maybeoperatorNoComma;
if (type == "operator") {
if (/\+\+|--/.test(value)) return cont(maybeoperator);
if (/\+\+|--/.test(value)) return cont(me);
if (value == "?") return cont(expression, expect(":"), expression);
return cont(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);
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(maybeoperator, expect(";"), poplex);
return pass(maybeoperatorComma, expect(";"), poplex);
}
function property(type) {
if (type == "variable") {cx.marked = "property"; return cont();}
Expand All @@ -308,7 +320,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
} else if (type == "number" || type == "string") {
cx.marked = type + " property";
}
if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression);
if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expressionNoComma);
}
function getterSetter(type) {
if (type == ":") return cont(expression);
Expand All @@ -318,7 +330,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function commasep(what, end) {
function proceed(type) {
if (type == ",") return cont(what, proceed);
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));
}
Expand Down Expand Up @@ -347,23 +363,32 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return pass();
}
function vardef2(type, value) {
if (value == "=") return cont(expression, vardef2);
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 cont(forspec2);
return pass(expression, expect(";"), forspec2);
}
function formaybein(_type, value) {
if (value == "in") return cont(expression);
return cont(maybeoperator, forspec2);
return cont(maybeoperatorComma, forspec2);
}
function forspec2(type, value) {
if (type == ";") return cont(forspec3);
if (value == "in") return cont(expression);
return cont(expression, expect(";"), forspec3);
return pass(expression, expect(";"), forspec3);
}
function forspec3(type) {
if (type != ")") cont(expression);
Expand Down Expand Up @@ -398,10 +423,10 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
state.lexical.align = false;
state.indented = stream.indentation();
}
if (stream.eatSpace()) return null;
if (state.tokenize != jsTokenComment && stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
if (type == "comment") return style;
state.lastType = type;
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
return parseJS(state, style, type, content, stream);
},

Expand All @@ -411,6 +436,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
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;
Expand Down
4 changes: 2 additions & 2 deletions mode/jinja2/jinja2.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
CodeMirror.defineMode("jinja2", function() {
var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",
var keywords = ["block", "endblock", "for", "endfor", "in", "true", "false",
"loop", "none", "self", "super", "if", "as", "not", "and",
"else", "import", "with", "without", "context"];
keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b");
Expand Down Expand Up @@ -38,5 +38,5 @@ CodeMirror.defineMode("jinja2", function() {
token: function (stream, state) {
return state.tokenize(stream, state);
}
};
};
});
76 changes: 38 additions & 38 deletions mode/less/less.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ CodeMirror.defineMode("less", function(config) {
function ret(style, tp) {type = tp; return style;}
//html tags
var tags = "a abbr acronym address applet area article aside audio b base basefont bdi bdo big blockquote body br button canvas caption cite code col colgroup command datalist dd del details dfn dir div dl dt em embed fieldset figcaption figure font footer form frame frameset h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins keygen kbd label legend li link map mark menu meta meter nav noframes noscript object ol optgroup option output p param pre progress q rp rt ruby s samp script section select small source span strike strong style sub summary sup table tbody td textarea tfoot th thead time title tr track tt u ul var video wbr".split(' ');

function inTagsArray(val){
for(var i=0; i<tags.length; i++)if(val === tags[i])return true;
}

var selectors = /(^\:root$|^\:nth\-child$|^\:nth\-last\-child$|^\:nth\-of\-type$|^\:nth\-last\-of\-type$|^\:first\-child$|^\:last\-child$|^\:first\-of\-type$|^\:last\-of\-type$|^\:only\-child$|^\:only\-of\-type$|^\:empty$|^\:link|^\:visited$|^\:active$|^\:hover$|^\:focus$|^\:target$|^\:lang$|^\:enabled^\:disabled$|^\:checked$|^\:first\-line$|^\:first\-letter$|^\:before$|^\:after$|^\:not$|^\:required$|^\:invalid$)/;

function tokenBase(stream, state) {
var ch = stream.next();

if (ch == "@") {stream.eatWhile(/[\w\-]/); return ret("meta", stream.current());}
else if (ch == "/" && stream.eat("*")) {
state.tokenize = tokenCComment;
Expand All @@ -41,7 +41,7 @@ CodeMirror.defineMode("less", function(config) {
}else{
if(type == "string" || type == "(")return ret("string", "string");
if(state.stack[state.stack.length-1] != undefined)return ret(null, ch);
stream.eatWhile(/[\a-zA-Z0-9\-_.\s]/);
stream.eatWhile(/[\a-zA-Z0-9\-_.\s]/);
if( /\/|\)|#/.test(stream.peek() || (stream.eatSpace() && stream.peek() == ")")) || stream.eol() )return ret("string", "string"); // let url(/images/logo.png) without quotes return as string
}
}
Expand All @@ -58,7 +58,7 @@ CodeMirror.defineMode("less", function(config) {
return ret(null, "select-op");
}
else if (/[;{}:\[\]()~\|]/.test(ch)) {
if(ch == ":"){
if(ch == ":"){
stream.eatWhile(/[a-z\\\-]/);
if( selectors.test(stream.current()) ){
return ret("tag", "tag");
Expand All @@ -69,15 +69,15 @@ CodeMirror.defineMode("less", function(config) {
if( selectors.test(stream.current().substring(1)) )return ret("tag", "tag");
return ret(null, ch);
}else{
return ret(null, ch);
return ret(null, ch);
}
}else if(ch == "~"){
if(type == "r")return ret("string", "string");
}else{
return ret(null, ch);
}
}
else if (ch == ".") {
else if (ch == ".") {
if(type == "(" || type == "string")return ret("string", "string"); // allow url(../image.png)
stream.eatWhile(/[\a-zA-Z0-9\-_]/);
if(stream.peek() == " ")stream.eatSpace();
Expand Down Expand Up @@ -106,7 +106,7 @@ CodeMirror.defineMode("less", function(config) {
else return ret("number", "unit");
}else{//when not a valid hexvalue in the current stream e.g. #footer
stream.eatWhile(/[\w\\\-]/);
return ret("atom", "tag");
return ret("atom", "tag");
}
}else{//when not a valid hexvalue length
stream.eatWhile(/[\w\\\-]/);
Expand All @@ -126,14 +126,14 @@ CodeMirror.defineMode("less", function(config) {
return ret("string", "string");
}else if(stream.peek() == "<" || stream.peek() == ">"){
return ret("tag", "tag");
}else if( /\(/.test(stream.peek()) ){
}else if( /\(/.test(stream.peek()) ){
return ret(null, ch);
}else if (stream.peek() == "/" && state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png)
return ret("string", "string");
}else if( stream.current().match(/\-\d|\-.\d/) ){ // match e.g.: -5px -0.4 etc... only colorize the minus sign
//commment out these 2 comment if you want the minus sign to be parsed as null -500px
//stream.backUp(stream.current().length-1);
//return ret(null, ch); //console.log( stream.current() );
//return ret(null, ch); //console.log( stream.current() );
return ret("number", "unit");
}else if( inTagsArray(stream.current().toLowerCase()) ){ // match html tags
return ret("tag", "tag");
Expand All @@ -156,30 +156,30 @@ CodeMirror.defineMode("less", function(config) {
stream.next();
var t_v = stream.peek() == ":" ? true : false;
if(!t_v){
var old_pos = stream.pos;
var sc = stream.current().length;
stream.eatWhile(/[a-z\\\-]/);
var new_pos = stream.pos;
if(stream.current().substring(sc-1).match(selectors) != null){
stream.backUp(new_pos-(old_pos-1));
return ret("tag", "tag");
} else stream.backUp(new_pos-(old_pos-1));
}else{
stream.backUp(1);
}
if(t_v)return ret("tag", "tag"); else return ret("variable", "variable");
}else{
return ret("variable", "variable");
var old_pos = stream.pos;
var sc = stream.current().length;
stream.eatWhile(/[a-z\\\-]/);
var new_pos = stream.pos;
if(stream.current().substring(sc-1).match(selectors) != null){
stream.backUp(new_pos-(old_pos-1));
return ret("tag", "tag");
} else stream.backUp(new_pos-(old_pos-1));
}else{
stream.backUp(1);
}
if(t_v)return ret("tag", "tag"); else return ret("variable", "variable");
}else{
return ret("variable", "variable");
}
}
}
}

function tokenSComment(stream, state) { // SComment = Slash comment
stream.skipToEnd();
state.tokenize = tokenBase;
return ret("comment", "comment");
}

function tokenCComment(stream, state) {
var maybeEnd = false, ch;
while ((ch = stream.next()) != null) {
Expand All @@ -191,7 +191,7 @@ CodeMirror.defineMode("less", function(config) {
}
return ret("comment", "comment");
}

function tokenSGMLComment(stream, state) {
var dashes = 0, ch;
while ((ch = stream.next()) != null) {
Expand All @@ -203,7 +203,7 @@ CodeMirror.defineMode("less", function(config) {
}
return ret("comment", "comment");
}

function tokenString(quote) {
return function(stream, state) {
var escaped = false, ch;
Expand All @@ -216,18 +216,18 @@ CodeMirror.defineMode("less", function(config) {
return ret("string", "string");
};
}

return {
startState: function(base) {
startState: function(base) {
return {tokenize: tokenBase,
baseIndent: base || 0,
stack: []};
},

token: function(stream, state) {
if (stream.eatSpace()) return null;
var style = state.tokenize(stream, state);

var context = state.stack[state.stack.length-1];
if (type == "hash" && context == "rule") style = "atom";
else if (style == "variable") {
Expand All @@ -237,7 +237,7 @@ CodeMirror.defineMode("less", function(config) {
/[\s,|\s\)|\s]/.test(stream.peek()) ? "tag" : type;
}
}

if (context == "rule" && /^[\{\};]$/.test(type))
state.stack.pop();
if (type == "{") {
Expand All @@ -249,18 +249,18 @@ CodeMirror.defineMode("less", function(config) {
else if (context == "{" && type != "comment") state.stack.push("rule");
return style;
},

indent: function(state, textAfter) {
var n = state.stack.length;
if (/^\}/.test(textAfter))
n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
return state.baseIndent + n * indentUnit;
},

electricChars: "}"
};
});

CodeMirror.defineMIME("text/x-less", "less");
if (!CodeMirror.mimeModes.hasOwnProperty("text/css"))
CodeMirror.defineMIME("text/css", "less");
CodeMirror.defineMIME("text/css", "less");
14 changes: 7 additions & 7 deletions mode/lua/lua.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's
// CodeMirror 1 mode.
// highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting

CodeMirror.defineMode("lua", function(config, parserConfig) {
var indentUnit = config.indentUnit;

Expand All @@ -12,7 +12,7 @@ CodeMirror.defineMode("lua", function(config, parserConfig) {
return new RegExp("^(?:" + words.join("|") + ")$", "i");
}
var specials = wordRE(parserConfig.specials || []);

// long list of standard functions from lua manual
var builtins = wordRE([
"_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load",
Expand Down Expand Up @@ -47,8 +47,8 @@ CodeMirror.defineMode("lua", function(config, parserConfig) {
"table.concat","table.insert","table.maxn","table.remove","table.sort"
]);
var keywords = wordRE(["and","break","elseif","false","nil","not","or","return",
"true","function", "end", "if", "then", "else", "do",
"while", "repeat", "until", "for", "in", "local" ]);
"true","function", "end", "if", "then", "else", "do",
"while", "repeat", "until", "for", "in", "local" ]);

var indentTokens = wordRE(["function", "if","repeat","do", "\\(", "{"]);
var dedentTokens = wordRE(["end", "until", "\\)", "}"]);
Expand All @@ -68,7 +68,7 @@ CodeMirror.defineMode("lua", function(config, parserConfig) {
return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state);
stream.skipToEnd();
return "comment";
}
}
if (ch == "\"" || ch == "'")
return (state.cur = string(ch))(stream, state);
if (ch == "[" && /[\[=]/.test(stream.peek()))
Expand Down Expand Up @@ -108,7 +108,7 @@ CodeMirror.defineMode("lua", function(config, parserConfig) {
return "string";
};
}

return {
startState: function(basecol) {
return {basecol: basecol || 0, indentDepth: 0, cur: normal};
Expand All @@ -121,7 +121,7 @@ CodeMirror.defineMode("lua", function(config, parserConfig) {
if (style == "variable") {
if (keywords.test(word)) style = "keyword";
else if (builtins.test(word)) style = "builtin";
else if (specials.test(word)) style = "variable-2";
else if (specials.test(word)) style = "variable-2";
}
if ((style != "comment") && (style != "string")){
if (indentTokens.test(word)) ++state.indentDepth;
Expand Down
78 changes: 39 additions & 39 deletions mode/markdown/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,22 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
if (aliases[a] in modes || aliases[a] in mimes)
modes[a] = aliases[a];
}

return function (lang) {
return modes[lang] ? CodeMirror.getMode(cmCfg, modes[lang]) : null;
};
}());

// Should underscores in words open/close em/strong?
if (modeCfg.underscoresBreakWords === undefined)
modeCfg.underscoresBreakWords = true;

// Turn on fenced code blocks? ("```" to start/end)
if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;

// Turn on task lists? ("- [ ] " and "- [x] ")
if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;

var codeDepth = 0;

var header = 'header'
Expand Down Expand Up @@ -109,7 +109,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
}

function blockNormal(stream, state) {

var prevLineIsList = (state.list !== false);
if (state.list !== false && state.indentationDiff >= 0) { // Continued list
if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
Expand All @@ -123,7 +123,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
state.list = false;
state.listDepth = 0;
}

if (state.indentationDiff >= 4) {
state.indentation -= 4;
stream.skipToEnd();
Expand Down Expand Up @@ -158,7 +158,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
switchBlock(stream, state, local);
return code;
}

return switchInline(stream, state, state.inline);
}

Expand Down Expand Up @@ -193,17 +193,17 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
// Inline
function getType(state) {
var styles = [];

if (state.taskOpen) { return "meta"; }
if (state.taskClosed) { return "property"; }

if (state.strong) { styles.push(strong); }
if (state.em) { styles.push(em); }

if (state.linkText) { styles.push(linktext); }

if (state.code) { styles.push(code); }

if (state.header) { styles.push(header); }
if (state.quote) { styles.push(state.quote % 2 ? quote1 : quote2); }
if (state.list !== false) {
Expand All @@ -224,37 +224,37 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
if (stream.match(textRE, true)) {
return getType(state);
}
return undefined;
return undefined;
}

function inlineNormal(stream, state) {
var style = state.text(stream, state);
if (typeof style !== 'undefined')
return style;

if (state.list) { // List marker (*, +, -, 1., etc)
state.list = null;
return getType(state);
}

if (state.taskList) {
var taskOpen = stream.match(taskListRE, true)[1] !== "x";
if (taskOpen) state.taskOpen = true;
else state.taskClosed = true;
state.taskList = false;
return getType(state);
}

state.taskOpen = false;
state.taskClosed = false;

var ch = stream.next();

if (ch === '\\') {
stream.next();
return getType(state);
}

// Matches link titles present on next line
if (state.linkTitle) {
state.linkTitle = false;
Expand All @@ -268,7 +268,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
return linkhref;
}
}

// If this block is changed, it may need to be updated in GFM mode
if (ch === '`') {
var t = getType(state);
Expand All @@ -289,7 +289,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
} else if (state.code) {
return getType(state);
}

if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
stream.match(/\[[^\]]*\]/);
state.inline = state.f = linkHref;
Expand All @@ -307,15 +307,15 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
state.inline = state.f = linkHref;
return type;
}

if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, true)) {
return switchInline(stream, state, inlineElement(linkinline, '>'));
}

if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, true)) {
return switchInline(stream, state, inlineElement(linkemail, '>'));
}

if (ch === '<' && stream.match(/^\w/, false)) {
if (stream.string.indexOf(">")!=-1) {
var atts = stream.string.substring(1,stream.string.indexOf(">"));
Expand All @@ -326,12 +326,12 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
stream.backUp(1);
return switchBlock(stream, state, htmlBlock);
}

if (ch === '<' && stream.match(/^\/\w*?>/)) {
state.md_inside = false;
return "tag";
}

var ignoreUnderscore = false;
if (!modeCfg.underscoresBreakWords) {
if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
Expand Down Expand Up @@ -368,7 +368,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
}
}
}

return getType(state);
}

Expand Down Expand Up @@ -414,7 +414,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
if (!savedInlineRE[endChar]) {
// Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)
endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
// Match any non-endChar, escaped character, as well as the closing
// Match any non-endChar, escaped character, as well as the closing
// endChar.
savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')');
}
Expand All @@ -434,17 +434,17 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
startState: function() {
return {
f: blockNormal,

prevLineHasContent: false,
thisLineHasContent: false,

block: blockNormal,
htmlState: CodeMirror.startState(htmlMode),
indentation: 0,

inline: inlineNormal,
text: handleText,

linkText: false,
linkTitle: false,
em: false,
Expand All @@ -460,17 +460,17 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
copyState: function(s) {
return {
f: s.f,

prevLineHasContent: s.prevLineHasContent,
thisLineHasContent: s.thisLineHasContent,

block: s.block,
htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
indentation: s.indentation,

localMode: s.localMode,
localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,

inline: s.inline,
text: s.text,
linkTitle: s.linkTitle,
Expand All @@ -497,10 +497,10 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {

// Reset state.header
state.header = false;

// Reset state.taskList
state.taskList = false;

// Reset state.code
state.code = false;

Expand Down
22 changes: 11 additions & 11 deletions mode/markdown/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,20 @@
"[comment `]");

// Unclosed backticks
// Instead of simply marking as CODE, it would be nice to have an
// Instead of simply marking as CODE, it would be nice to have an
// incomplete flag for CODE, that is styled slightly different.
MT("unclosedBackticks",
"foo [comment `bar]");

// Per documentation: "To include a literal backtick character within a
// code span, you can use multiple backticks as the opening and closing
// Per documentation: "To include a literal backtick character within a
// code span, you can use multiple backticks as the opening and closing
// delimiters"
MT("doubleBackticks",
"[comment ``foo ` bar``]");

// Tests based on Dingus
// http://daringfireball.net/projects/markdown/dingus
//
//
// Multiple backticks within an inline code block
MT("consecutiveBackticks",
"[comment `foo```bar`]");
Expand Down Expand Up @@ -98,10 +98,10 @@
// Setext headers - H1, H2
// Per documentation, "Any number of underlining =’s or -’s will work."
// http://daringfireball.net/projects/markdown/syntax#header
// Ideally, the text would be marked as `header` as well, but this is
// not really feasible at the moment. So, instead, we're testing against
// Ideally, the text would be marked as `header` as well, but this is
// not really feasible at the moment. So, instead, we're testing against
// what works today, to avoid any regressions.
//
//
// Check if single underlining = works
MT("setextH1",
"foo",
Expand Down Expand Up @@ -368,7 +368,7 @@
" [comment world]",
" [comment foo]",
" [variable-2 bar]");

// List nesting edge cases
MT("listNested",
"[variable-2 * foo]",
Expand Down Expand Up @@ -548,7 +548,7 @@
MT("emInWordUnderscore",
"foo[em _bar_]hello");

// Per documentation: "...surround an * or _ with spaces, it’ll be
// Per documentation: "...surround an * or _ with spaces, it’ll be
// treated as a literal asterisk or underscore."

MT("emEscapedBySpaceIn",
Expand All @@ -558,7 +558,7 @@
"foo _ bar[em _hello_]world");

// Unclosed emphasis characters
// Instead of simply marking as EM / STRONG, it would be nice to have an
// Instead of simply marking as EM / STRONG, it would be nice to have an
// incomplete flag for EM and STRONG, that is styled slightly different.
MT("emIncompleteAsterisk",
"foo [em *bar]");
Expand Down Expand Up @@ -625,7 +625,7 @@


// Tests to make sure GFM-specific things aren't getting through

MT("taskList",
"[variable-2 * [ ]] bar]");

Expand Down
1 change: 1 addition & 0 deletions mode/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CodeMirror.modeInfo = [
{name: 'diff', mime: 'text/x-diff', mode: 'diff'},
{name: 'ECL', mime: 'text/x-ecl', mode: 'ecl'},
{name: 'Erlang', mime: 'text/x-erlang', mode: 'erlang'},
{name: 'Gas', mime: 'text/x-gas', mode: 'gas'},
{name: 'GitHub Flavored Markdown', mode: 'gfm'},
{name: 'GO', mime: 'text/x-go', mode: 'go'},
{name: 'Groovy', mime: 'text/x-groovy', mode: 'groovy'},
Expand Down
114 changes: 57 additions & 57 deletions mode/mirc/mirc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,65 +8,65 @@ CodeMirror.defineMode("mirc", function() {
}
var specials = parseWords("$! $$ $& $? $+ $abook $abs $active $activecid " +
"$activewid $address $addtok $agent $agentname $agentstat $agentver " +
"$alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime " +
"$asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind " +
"$binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes " +
"$chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color " +
"$com $comcall $comchan $comerr $compact $compress $comval $cos $count " +
"$cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight " +
"$dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress " +
"$deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll " +
"$dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error " +
"$eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir " +
"$finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve " +
"$fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt " +
"$group $halted $hash $height $hfind $hget $highlight $hnick $hotline " +
"$hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil " +
"$inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect " +
"$insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile " +
"$isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive " +
"$lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock " +
"$lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer " +
"$maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext " +
"$menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode " +
"$modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile " +
"$nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly " +
"$opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree " +
"$pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo " +
"$readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex " +
"$reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline " +
"$sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin " +
"$site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname " +
"$sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped " +
"$syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp " +
"$timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel " +
"$ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver " +
"$version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor");
"$alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime " +
"$asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind " +
"$binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes " +
"$chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color " +
"$com $comcall $comchan $comerr $compact $compress $comval $cos $count " +
"$cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight " +
"$dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress " +
"$deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll " +
"$dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error " +
"$eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir " +
"$finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve " +
"$fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt " +
"$group $halted $hash $height $hfind $hget $highlight $hnick $hotline " +
"$hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil " +
"$inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect " +
"$insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile " +
"$isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive " +
"$lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock " +
"$lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer " +
"$maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext " +
"$menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode " +
"$modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile " +
"$nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly " +
"$opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree " +
"$pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo " +
"$readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex " +
"$reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline " +
"$sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin " +
"$site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname " +
"$sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped " +
"$syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp " +
"$timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel " +
"$ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver " +
"$version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor");
var keywords = parseWords("abook ajinvite alias aline ame amsg anick aop auser autojoin avoice " +
"away background ban bcopy beep bread break breplace bset btrunc bunset bwrite " +
"channel clear clearall cline clipboard close cnick color comclose comopen " +
"comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver " +
"debug dec describe dialog did didtok disable disconnect dlevel dline dll " +
"dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace " +
"drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable " +
"events exit fclose filter findtext finger firewall flash flist flood flush " +
"flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove " +
"gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd " +
"halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear " +
"ialmark identd if ignore iline inc invite iuser join kick linesep links list " +
"load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice " +
"notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice " +
"qme qmsg query queryn quit raw reload remini remote remove rename renwin " +
"reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini " +
"say scid scon server set showmirc signam sline sockaccept sockclose socklist " +
"socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite " +
"sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize " +
"toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho " +
"var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum " +
"isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower " +
"isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs " +
"elseif else goto menu nicklist status title icon size option text edit " +
"button check radio box scroll list combo link tab item");
"channel clear clearall cline clipboard close cnick color comclose comopen " +
"comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver " +
"debug dec describe dialog did didtok disable disconnect dlevel dline dll " +
"dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace " +
"drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable " +
"events exit fclose filter findtext finger firewall flash flist flood flush " +
"flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove " +
"gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd " +
"halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear " +
"ialmark identd if ignore iline inc invite iuser join kick linesep links list " +
"load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice " +
"notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice " +
"qme qmsg query queryn quit raw reload remini remote remove rename renwin " +
"reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini " +
"say scid scon server set showmirc signam sline sockaccept sockclose socklist " +
"socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite " +
"sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize " +
"toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho " +
"var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum " +
"isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower " +
"isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs " +
"elseif else goto menu nicklist status title icon size option text edit " +
"button check radio box scroll list combo link tab item");
var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch");
var isOperatorChar = /[+\-*&%=<>!?^\/\|]/;
function chain(stream, state, f) {
Expand Down
Loading