8 changes: 8 additions & 0 deletions demo/theme.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<link rel="stylesheet" href="../theme/abcdef.css">
<link rel="stylesheet" href="../theme/ambiance.css">
<link rel="stylesheet" href="../theme/base16-dark.css">
<link rel="stylesheet" href="../theme/bespin.css">
<link rel="stylesheet" href="../theme/base16-light.css">
<link rel="stylesheet" href="../theme/blackboard.css">
<link rel="stylesheet" href="../theme/cobalt.css">
Expand All @@ -18,7 +19,9 @@
<link rel="stylesheet" href="../theme/eclipse.css">
<link rel="stylesheet" href="../theme/elegant.css">
<link rel="stylesheet" href="../theme/erlang-dark.css">
<link rel="stylesheet" href="../theme/hopscotch.css">
<link rel="stylesheet" href="../theme/icecoder.css">
<link rel="stylesheet" href="../theme/isotope.css">
<link rel="stylesheet" href="../theme/lesser-dark.css">
<link rel="stylesheet" href="../theme/liquibyte.css">
<link rel="stylesheet" href="../theme/material.css">
Expand All @@ -32,6 +35,7 @@
<link rel="stylesheet" href="../theme/paraiso-dark.css">
<link rel="stylesheet" href="../theme/paraiso-light.css">
<link rel="stylesheet" href="../theme/pastel-on-dark.css">
<link rel="stylesheet" href="../theme/railscasts.css">
<link rel="stylesheet" href="../theme/rubyblue.css">
<link rel="stylesheet" href="../theme/seti.css">
<link rel="stylesheet" href="../theme/solarized.css">
Expand Down Expand Up @@ -89,14 +93,17 @@ <h2>Theme Demo</h2>
<option>ambiance</option>
<option>base16-dark</option>
<option>base16-light</option>
<option>bespin</option>
<option>blackboard</option>
<option>cobalt</option>
<option>colorforth</option>
<option>dracula</option>
<option>eclipse</option>
<option>elegant</option>
<option>erlang-dark</option>
<option>hopscotch</option>
<option>icecoder</option>
<option>isotope</option>
<option>lesser-dark</option>
<option>liquibyte</option>
<option>material</option>
Expand All @@ -110,6 +117,7 @@ <h2>Theme Demo</h2>
<option>paraiso-dark</option>
<option>paraiso-light</option>
<option>pastel-on-dark</option>
<option>railscasts</option>
<option>rubyblue</option>
<option>seti</option>
<option>solarized dark</option>
Expand Down
2 changes: 1 addition & 1 deletion doc/compress.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ <h2>Script compression helper</h2>
<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=5.8.0;f=">5.8</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.7.0;f=">5.7</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.6.0;f=">5.6</option>
<option value="http://marijnhaverbeke.nl/git/codemirror?a=blob_plain;hb=5.5.0;f=">5.5</option>
Expand Down Expand Up @@ -154,7 +155,6 @@ <h2>Script compression helper</h2>
<option value="http://codemirror.net/mode/javascript/javascript.js">javascript.js</option>
<option value="http://codemirror.net/mode/jinja2/jinja2.js">jinja2.js</option>
<option value="http://codemirror.net/mode/julia/julia.js">julia.js</option>
<option value="http://codemirror.net/mode/kotlin/kotlin.js">kotlin.js</option>
<option value="http://codemirror.net/mode/livescript/livescript.js">livescript.js</option>
<option value="http://codemirror.net/mode/lua/lua.js">lua.js</option>
<option value="http://codemirror.net/mode/markdown/markdown.js">markdown.js</option>
Expand Down
29 changes: 22 additions & 7 deletions doc/manual.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
<section class=first id=overview>
<h2 style="position: relative">
User manual and reference guide
<span style="color: #888; font-size: 1rem; position: absolute; right: 0; bottom: 0">version 5.7.0</span>
<span style="color: #888; font-size: 1rem; position: absolute; right: 0; bottom: 0">version 5.8.0</span>
</h2>

<p>CodeMirror is a code-editor component that can be embedded in
Expand Down Expand Up @@ -421,6 +421,13 @@ <h2>Configuration</h2>
<dt id="option_dragDrop"><code><strong>dragDrop</strong>: boolean</code></dt>
<dd>Controls whether drag-and-drop is enabled. On by default.</dd>

<dt id="option_allowDropFileTypes"><code><strong>allowDropFileTypes</strong>: array&lt;string&gt;</code></dt>
<dd>When set (default is <code>null</code>) only files whose
type is in the array can be dropped into the editor. The strings
should be MIME types, and will be checked against
the <a href="https://w3c.github.io/FileAPI/#dfn-type"><code>type</code></a>
of the <code>File</code> object as reported by the browser.</dd>

<dt id="option_cursorBlinkRate"><code><strong>cursorBlinkRate</strong>: number</code></dt>
<dd>Half-period in milliseconds used for cursor blinking. The default blink
rate is 530ms. By setting this to zero, blinking can be disabled. A
Expand Down Expand Up @@ -1304,7 +1311,7 @@ <h3 id="api_selection">Cursor and selection methods</h3>
collapsed or both non-collapsed), the new one will replace the
old one. When it starts with <code>*</code>, it will always
replace the previous event (if that had the same origin).
Built-in motion uses the <code>"+move"</code> origin.</dd>
Built-in motion uses the <code>"+move"</code> origin. User input uses the <code>"+input"</code> origin.</dd>
<dt id="selection_bias"><code><strong>bias</strong>: number</code></dt>
<dd>Determine the direction into which the selection endpoints
should be adjusted when they fall inside
Expand Down Expand Up @@ -2306,9 +2313,12 @@ <h2 id="addons">Addons</h2>
demo</a>.</dd>

<dt id="addon_comment"><a href="../addon/comment/comment.js"><code>comment/comment.js</code></a></dt>
<dd>Addon for commenting and uncommenting code. Adds three
<dd>Addon for commenting and uncommenting code. Adds four
methods to CodeMirror instances:
<dl>
<dt id="toggleComment"><code><strong>toggleComment</strong>(from: {line, ch}, to: {line, ch}, ?options: object)</code></dt>
<dd>Tries to uncomment the current selection, and if that
fails, line-comments it.</dd>
<dt id="lineComment"><code><strong>lineComment</strong>(from: {line, ch}, to: {line, ch}, ?options: object)</code></dt>
<dd>Set the lines in the given range to be line comments. Will
fall back to <code>blockComment</code> when no line comment
Expand Down Expand Up @@ -2346,8 +2356,8 @@ <h2 id="addons">Addons</h2>
</dl>
The addon also defines
a <code>toggleComment</code> <a href="#commands">command</a>,
which will try to uncomment the current selection, and if that
fails, line-comments it.</dd>
which is a shorthand command for calling
<code>toggleComment</code> with no options.</dd>

<dt id="addon_foldcode"><a href="../addon/fold/foldcode.js"><code>fold/foldcode.js</code></a></dt>
<dd>Helps with code folding. Adds a <code>foldCode</code> method
Expand Down Expand Up @@ -2481,7 +2491,9 @@ <h2 id="addons">Addons</h2>
Pass <code>"\n"</code> for <code>open</code> or <code>close</code>
if you want to switch on a blank line.
<ul><li>When <code>delimStyle</code> is specified, it will be the token
style returned for the delimiter tokens.</li>
style returned for the delimiter tokens (as well as
<code>[delimStyle]-open</code> on the opening token and
<code>[delimStyle]-close</code> on the closing token).</li>
<li>When <code>innerStyle</code> is specified, it will be the token
style added for each inner mode token.</li>
<li>When <code>parseDelimiters</code> is true, the content of
Expand Down Expand Up @@ -2549,7 +2561,10 @@ <h2 id="addons">Addons</h2>
arguments <code>(cm, callback, ?options)</code>, and the
completion interface will only be popped up when the hinting
function calls the callback, passing it the object holding the
completions.</dd>
completions. By default, hinting only works when there is no
selection. You can give a hinting function
a <code>supportsSelection</code> property with a truthy value
to indicate that it supports selections.</dd>
<dt><code><strong>completeSingle</strong>: boolean</code></dt>
<dd>Determines whether, when only a single completion is
available, it is completed without showing the dialog.
Expand Down
1 change: 1 addition & 0 deletions doc/realworld.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ <h2>CodeMirror real-world uses</h2>
<li><a href="http://amber-lang.net/">Amber</a> (JavaScript-based Smalltalk system)</li>
<li><a href="http://apachegui.ca/">Apache GUI</a></li>
<li><a href="http://apeye.org/">APEye</a> (tool for testing &amp; documenting APIs)</li>
<li><a href="https://github.com/google/appengine-codiad">Appengine Codiad</a></li>
<li><a href="https://chrome.google.com/webstore/detail/better-text-viewer/lcaidopdffhfemoefoaadecppnjdknkc">Better Text Viewer</a> (plain text reader app for Chrome)</li>
<li><a href="http://blog.bitbucket.org/2013/05/14/edit-your-code-in-the-cloud-with-bitbucket/">Bitbucket</a> (code hosting)</li>
<li><a href="http://buzz.blogger.com/2013/04/improvements-to-blogger-template-html.html">Blogger's template editor</a></li>
Expand Down
15 changes: 14 additions & 1 deletion doc/releases.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,20 @@ <h2>Release notes and version history</h2>

<h2>Version 5.x</h2>

<p class="rel">20-08-2015: <a href="http://codemirror.net/codemirror-5.7.zip">Version 5.7</a>:</p>
<p class="rel">20-10-2015: <a href="http://codemirror.net/codemirror-5.8.zip">Version 5.8</a>:</p>

<ul class="rel-note">
<li>Fixes an infinite loop in
the <a href="manual.html#addon_hardwrap">hardwrap
addon</a></li>
<li>New modes: <a href="../mode/nsis/index.html">NSIS</a>, <a href="../mode/clike/index.html">Ceylon</a></li>
<li>The Kotlin mode is now a <a href="../mode/clike/index.html">clike</a> dialect, rather than a stand-alone mode</li>
<li>New option: <a href="manual.html#option_allowDropFileTypes"><code>allowDropFileTypes</code></a>. Binary files can no longer be dropped into CodeMirror</li>
<li>New themes: <a href="../demo/theme.html#bespin">bespin</a>, <a href="../demo/theme.html#hopscotch">hopscotch</a>, <a href="../demo/theme.html#isotope">isotope</a>, <a href="../demo/theme.html#railscasts">railscasts</a></li>
<li>Full <a href="https://github.com/codemirror/CodeMirror/compare/5.7.0...5.8.0">list of patches</a></li>
</ul>

<p class="rel">20-09-2015: <a href="http://codemirror.net/codemirror-5.7.zip">Version 5.7</a>:</p>

<ul class="rel-note">
<li>New modes: <a href="../mode/vue/index.html">Vue</a>, <a href="../mode/oz/index.html">Oz</a>, <a href="../mode/mscgen/index.html">MscGen</a> (and dialects), <a href="../mode/css/gss.html">Closure Stylesheets</a></li>
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ <h2>This is CodeMirror</h2>
</div>
</div>
<div class=actionsleft>
Get the current version: <a href="http://codemirror.net/codemirror.zip">5.7</a>.<br>
Get the current version: <a href="http://codemirror.net/codemirror.zip">5.8</a>.<br>
You can see the <a href="https://github.com/codemirror/codemirror" title="Github repository">code</a> or<br>
read the <a href="doc/releases.html">release notes</a>.<br>
There is a <a href="doc/compress.html">minification helper</a>.
Expand Down
4 changes: 3 additions & 1 deletion keymap/sublime.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,9 @@
});
};

map[ctrl + "/"] = "toggleComment";
map[ctrl + "/"] = function(cm) {
cm.toggleComment({ indent: true });
}

cmds[map[ctrl + "J"] = "joinLines"] = function(cm) {
var ranges = cm.listSelections(), joined = [];
Expand Down
87 changes: 54 additions & 33 deletions lib/codemirror.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,29 @@

// Kludges for bugs and behavior differences that can't be feature
// detected are enabled based on userAgent etc sniffing.
var userAgent = navigator.userAgent;
var platform = navigator.platform;

var gecko = /gecko\/\d/i.test(navigator.userAgent);
var ie_upto10 = /MSIE \d/.test(navigator.userAgent);
var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);
var gecko = /gecko\/\d/i.test(userAgent);
var ie_upto10 = /MSIE \d/.test(userAgent);
var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
var ie = ie_upto10 || ie_11up;
var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
var webkit = /WebKit\//.test(navigator.userAgent);
var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
var chrome = /Chrome\//.test(navigator.userAgent);
var presto = /Opera\//.test(navigator.userAgent);
var webkit = /WebKit\//.test(userAgent);
var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
var chrome = /Chrome\//.test(userAgent);
var presto = /Opera\//.test(userAgent);
var safari = /Apple Computer/.test(navigator.vendor);
var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
var phantom = /PhantomJS/.test(navigator.userAgent);
var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
var phantom = /PhantomJS/.test(userAgent);

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

var presto_version = presto && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
if (presto_version) presto_version = Number(presto_version[1]);
if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
// Some browsers use the wrong event properties to signal cmd/ctrl on OS X
Expand Down Expand Up @@ -3821,9 +3823,15 @@
if (files && files.length && window.FileReader && window.File) {
var n = files.length, text = Array(n), read = 0;
var loadFile = function(file, i) {
if (cm.options.allowDropFileTypes &&
indexOf(cm.options.allowDropFileTypes, file.type) == -1)
return;

var reader = new FileReader;
reader.onload = operation(cm, function() {
text[i] = reader.result;
var content = reader.result;
if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = "";
text[i] = content;
if (++read == n) {
pos = clipPos(cm.doc, pos);
var change = {from: pos, to: pos,
Expand Down Expand Up @@ -3965,8 +3973,9 @@

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

// Webkit browsers on OS X abort momentum scrolls when the target
// of the scroll event is removed from the scrollable element.
Expand All @@ -3990,10 +3999,15 @@
// scrolling entirely here. It'll be slightly off from native, but
// better than glitching out.
if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
if (dy)
if (dy && canScrollY)
setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
e_preventDefault(e);
// Only prevent default scrolling if vertical scrolling is
// actually possible. Otherwise, it causes vertical scroll
// jitter on OSX trackpads when deltaX is small and deltaY
// is large (issue #3579)
if (!dy || (dy && canScrollY))
e_preventDefault(e);
display.wheelStartX = null; // Abort measurement, if in progress
return;
}
Expand Down Expand Up @@ -4221,6 +4235,7 @@
// right-click take effect on it.
function onContextMenu(cm, e) {
if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;
if (signalDOMEvent(cm, e, "contextmenu")) return;
cm.display.input.onContextMenu(e);
}

Expand Down Expand Up @@ -5404,6 +5419,7 @@
});
option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
option("dragDrop", true, dragDropChanged);
option("allowDropFileTypes", null);

option("cursorBlinkRate", 530);
option("cursorScrollMargin", 0);
Expand Down Expand Up @@ -5708,8 +5724,8 @@
var range = cm.listSelections()[i];
cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input");
cm.indentLine(range.from().line + 1, null, true);
ensureCursorVisible(cm);
}
ensureCursorVisible(cm);
});
},
toggleOverwrite: function(cm) {cm.toggleOverwrite();}
Expand Down Expand Up @@ -7542,7 +7558,7 @@
removeLineWidget: function(widget) { widget.clear(); },

markText: function(from, to, options) {
return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range");
},
setBookmark: function(pos, options) {
var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
Expand Down Expand Up @@ -8103,24 +8119,30 @@
}
};

var noHandlers = []
function getHandlers(emitter, type, copy) {
var arr = emitter._handlers && emitter._handlers[type]
if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers
else return arr || noHandlers
}

var off = CodeMirror.off = function(emitter, type, f) {
if (emitter.removeEventListener)
emitter.removeEventListener(type, f, false);
else if (emitter.detachEvent)
emitter.detachEvent("on" + type, f);
else {
var arr = emitter._handlers && emitter._handlers[type];
if (!arr) return;
for (var i = 0; i < arr.length; ++i)
if (arr[i] == f) { arr.splice(i, 1); break; }
var handlers = getHandlers(emitter, type, false)
for (var i = 0; i < handlers.length; ++i)
if (handlers[i] == f) { handlers.splice(i, 1); break; }
}
};

var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
var arr = emitter._handlers && emitter._handlers[type];
if (!arr) return;
var handlers = getHandlers(emitter, type, true)
if (!handlers.length) return;
var args = Array.prototype.slice.call(arguments, 2);
for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args);
};

var orphanDelayedCallbacks = null;
Expand All @@ -8133,8 +8155,8 @@
// them to be executed when the last operation ends, or, if no
// operation is active, when a timeout fires.
function signalLater(emitter, type /*, values...*/) {
var arr = emitter._handlers && emitter._handlers[type];
if (!arr) return;
var arr = getHandlers(emitter, type, false)
if (!arr.length) return;
var args = Array.prototype.slice.call(arguments, 2), list;
if (operationGroup) {
list = operationGroup.delayedCallbacks;
Expand Down Expand Up @@ -8174,8 +8196,7 @@
}

function hasHandler(emitter, type) {
var arr = emitter._handlers && emitter._handlers[type];
return arr && arr.length > 0;
return getHandlers(emitter, type).length > 0
}

// Add on and off methods to a constructor's prototype, to make
Expand Down Expand Up @@ -8829,7 +8850,7 @@

// THE END

CodeMirror.version = "5.7.0";
CodeMirror.version = "5.8.0";

return CodeMirror;
});
155 changes: 140 additions & 15 deletions mode/clike/clike.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
multiLineStrings = parserConfig.multiLineStrings,
indentStatements = parserConfig.indentStatements !== false,
indentSwitch = parserConfig.indentSwitch !== false,
namespaceSeparator = parserConfig.namespaceSeparator;
var isOperatorChar = /[+\-*&%=<>!?|\/]/;
namespaceSeparator = parserConfig.namespaceSeparator,
isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/,
isNumberChar = parserConfig.isNumberChar || /\d/,
isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
endStatement = parserConfig.endStatement || /^[;:,]$/;

var curPunc, isDefKeyword;

Expand All @@ -40,11 +43,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
if (isPunctuationChar.test(ch)) {
curPunc = ch;
return null;
}
if (/\d/.test(ch)) {
if (isNumberChar.test(ch)) {
stream.eatWhile(/[\w\.]/);
return "number";
}
Expand All @@ -67,17 +70,17 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
stream.eatWhile(/[\w\$_\xa1-\uffff]/);

var cur = stream.current();
if (keywords.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
if (defKeywords.propertyIsEnumerable(cur)) isDefKeyword = true;
if (contains(keywords, cur)) {
if (contains(blockKeywords, cur)) curPunc = "newstatement";
if (contains(defKeywords, cur)) isDefKeyword = true;
return "keyword";
}
if (types.propertyIsEnumerable(cur)) return "variable-3";
if (builtin.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
if (contains(types, cur)) return "variable-3";
if (contains(builtin, cur)) {
if (contains(blockKeywords, cur)) curPunc = "newstatement";
return "builtin";
}
if (atoms.propertyIsEnumerable(cur)) return "atom";
if (contains(atoms, cur)) return "atom";
return "variable";
}

Expand Down Expand Up @@ -168,8 +171,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
if (style == "comment" || style == "meta") return style;
if (ctx.align == null) ctx.align = true;

if ((curPunc == ";" || curPunc == ":" || curPunc == ","))
while (isStatement(state.context.type)) popContext(state);
if (endStatement.test(curPunc)) while (isStatement(state.context.type)) popContext(state);
else if (curPunc == "{") pushContext(state, stream.column(), "}");
else if (curPunc == "[") pushContext(state, stream.column(), "]");
else if (curPunc == "(") pushContext(state, stream.column(), ")");
Expand Down Expand Up @@ -212,6 +214,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
if (isStatement(ctx.type) && firstChar == "}") ctx = ctx.prev;
if (hooks.indent) {
var hook = hooks.indent(state, ctx, textAfter);
if (typeof hook == "number") return hook
}
var closing = firstChar == ctx.type;
var switchBlock = ctx.prev && ctx.prev.type == "switchstatement";
if (isStatement(ctx.type))
Expand All @@ -238,6 +244,13 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
function contains(words, word) {
if (typeof words === "function") {
return words(word);
} else {
return words.propertyIsEnumerable(word);
}
}
var cKeywords = "auto if break case register continue return default do sizeof " +
"static else struct switch extern typedef float union for " +
"goto while enum const volatile";
Expand Down Expand Up @@ -413,6 +426,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
defKeywords: words("class interface package enum"),
typeFirstDefinitions: true,
atoms: words("true false null"),
endStatement: /^[;:]$/,
hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);
Expand Down Expand Up @@ -468,7 +482,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
keywords: words(

/* scala */
"abstract case catch class def do else extends false final finally for forSome if " +
"abstract case catch class def do else extends final finally for forSome if " +
"implicit import lazy match new null object override package private protected return " +
"sealed super this throw trait try type val var while with yield _ : = => <- <: " +
"<% >: # @ " +
Expand Down Expand Up @@ -516,6 +530,34 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
modeProps: {closeBrackets: {triples: '"'}}
});

def("text/x-kotlin", {
name: "clike",
keywords: words(
/*keywords*/
"package as typealias class interface this super val " +
"var fun for is in This throw return " +
"break continue object if else while do try when !in !is as?" +

/*soft keywords*/
"file import where by get set abstract enum open inner override private public internal " +
"protected catch finally out final vararg reified dynamic companion constructor init " +
"sealed field property receiver param sparam lateinit data inline noinline tailrec " +
"external annotation crossinline"
),
types: words(
/* 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"
),
multiLineStrings: true,
blockKeywords: words("catch class do else finally for if where try while enum"),
defKeywords: words("class val var object package interface fun"),
atoms: words("true false null this"),
modeProps: {closeBrackets: {triples: '"'}}
});

def(["x-shader/x-vertex", "x-shader/x-fragment"], {
name: "clike",
keywords: words("sampler1D sampler2D sampler3D samplerCube " +
Expand Down Expand Up @@ -598,7 +640,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
stream.eatWhile(/[\w\$]/);
return "keyword";
},
"#": cppHook
"#": cppHook,
indent: function(_state, ctx, textAfter) {
if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented
}
},
modeProps: {fold: "brace"}
});
Expand All @@ -616,4 +661,84 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
modeProps: {fold: ["brace", "include"]}
});

// Ceylon Strings need to deal with interpolation
var stringTokenizer = null;
function tokenCeylonString(type) {
return function(stream, state) {
var escaped = false, next, end = false;
while (!stream.eol()) {
if (!escaped && stream.match('"') &&
(type == "single" || stream.match('""'))) {
end = true;
break;
}
if (!escaped && stream.match('``')) {
stringTokenizer = tokenCeylonString(type);
end = true;
break;
}
next = stream.next();
escaped = type == "single" && !escaped && next == "\\";
}
if (end)
state.tokenize = null;
return "string";
}
}

def("text/x-ceylon", {
name: "clike",
keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" +
" exists extends finally for function given if import in interface is let module new" +
" nonempty object of out outer package return satisfies super switch then this throw" +
" try value void while"),
types: function(word) {
// In Ceylon all identifiers that start with an uppercase are types
var first = word.charAt(0);
return (first === first.toUpperCase() && first !== first.toLowerCase());
},
blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"),
defKeywords: words("class dynamic function interface module object package value"),
builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" +
" native optional sealed see serializable shared suppressWarnings tagged throws variable"),
isPunctuationChar: /[\[\]{}\(\),;\:\.`]/,
isOperatorChar: /[+\-*&%=<>!?|^~:\/]/,
isNumberChar: /[\d#$]/,
multiLineStrings: true,
typeFirstDefinitions: true,
atoms: words("true false null larger smaller equal empty finished"),
indentSwitch: false,
styleDefs: false,
hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);
return "meta";
},
'"': function(stream, state) {
state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single");
return state.tokenize(stream, state);
},
'`': function(stream, state) {
if (!stringTokenizer || !stream.match('`')) return false;
state.tokenize = stringTokenizer;
stringTokenizer = null;
return state.tokenize(stream, state);
},
"'": function(stream) {
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
return "atom";
},
token: function(_stream, state, style) {
if ((style == "variable" || style == "variable-3") &&
state.prevToken == ".") {
return "variable-2";
}
}
},
modeProps: {
fold: ["brace", "import"],
closeBrackets: {triples: '"'}
}
});

});
112 changes: 110 additions & 2 deletions mode/clike/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,103 @@ <h2>Scala example</h2>
}
</textarea></div>

<h2>Kotlin mode</h2>

<div><textarea id="kotlin-code">
package org.wasabi.http

import java.util.concurrent.Executors
import java.net.InetSocketAddress
import org.wasabi.app.AppConfiguration
import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioServerSocketChannel
import org.wasabi.app.AppServer

public class HttpServer(private val appServer: AppServer) {

val bootstrap: ServerBootstrap
val primaryGroup: NioEventLoopGroup
val workerGroup: NioEventLoopGroup

init {
// Define worker groups
primaryGroup = NioEventLoopGroup()
workerGroup = NioEventLoopGroup()

// Initialize bootstrap of server
bootstrap = ServerBootstrap()

bootstrap.group(primaryGroup, workerGroup)
bootstrap.channel(javaClass<NioServerSocketChannel>())
bootstrap.childHandler(NettyPipelineInitializer(appServer))
}

public fun start(wait: Boolean = true) {
val channel = bootstrap.bind(appServer.configuration.port)?.sync()?.channel()

if (wait) {
channel?.closeFuture()?.sync()
}
}

public fun stop() {
// Shutdown all event loops
primaryGroup.shutdownGracefully()
workerGroup.shutdownGracefully()

// Wait till all threads are terminated
primaryGroup.terminationFuture().sync()
workerGroup.terminationFuture().sync()
}
}
</textarea></div>

<h2>Ceylon mode</h2>

<div><textarea id="ceylon-code">
"Produces the [[stream|Iterable]] that results from repeated
application of the given [[function|next]] to the given
[[first]] element of the stream, until the function first
returns [[finished]]. If the given function never returns
`finished`, the resulting stream is infinite.

For example:

loop(0)(2.plus).takeWhile(10.largerThan)

produces the stream `{ 0, 2, 4, 6, 8 }`."
tagged("Streams")
shared {Element+} loop&lt;Element&gt;(
"The first element of the resulting stream."
Element first)(
"The function that produces the next element of the
stream, given the current element. The function may
return [[finished]] to indicate the end of the
stream."
Element|Finished next(Element element))
=&gt; let (start = first)
object satisfies {Element+} {
first =&gt; start;
empty =&gt; false;
function nextElement(Element element)
=&gt; next(element);
iterator()
=&gt; object satisfies Iterator&lt;Element&gt; {
variable Element|Finished current = start;
shared actual Element|Finished next() {
if (!is Finished result = current) {
current = nextElement(result);
return result;
}
else {
return finished;
}
}
};
};
</textarea></div>

<script>
var cEditor = CodeMirror.fromTextArea(document.getElementById("c-code"), {
lineNumbers: true,
Expand All @@ -232,6 +329,16 @@ <h2>Scala example</h2>
matchBrackets: true,
mode: "text/x-scala"
});
var kotlinEditor = CodeMirror.fromTextArea(document.getElementById("kotlin-code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-kotlin"
});
var ceylonEditor = CodeMirror.fromTextArea(document.getElementById("ceylon-code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-ceylon"
});
var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
</script>
Expand All @@ -247,6 +354,7 @@ <h2>Scala example</h2>
(Java), <code>text/x-csharp</code> (C#),
<code>text/x-objectivec</code> (Objective-C),
<code>text/x-scala</code> (Scala), <code>text/x-vertex</code>
and <code>x-shader/x-fragment</code> (shader programs),
<code>text/x-squirrel</code> (Squirrel).</p>
<code>x-shader/x-fragment</code> (shader programs),
<code>text/x-squirrel</code> (Squirrel) and
<code>text/x-ceylon</code> (Ceylon)</p>
</article>
11 changes: 0 additions & 11 deletions mode/coffeescript/coffeescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,17 +267,6 @@ CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
var style = state.tokenize(stream, state);
var current = stream.current();

// Handle "." connected identifiers
if (false && current === ".") {
style = state.tokenize(stream, state);
current = stream.current();
if (/^\.[\w$]+$/.test(current)) {
return "variable";
} else {
return ERRORCLASS;
}
}

// Handle scope changes.
if (current === "return") {
state.dedent = true;
Expand Down
2 changes: 2 additions & 0 deletions mode/css/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
if (type == "}" || type == ";") return popAndPass(type, stream, state);
if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");

if (type == "interpolation") return pushContext(state, stream, "interpolation");

if (type == "word") {
var word = stream.current().toLowerCase();
if (word == "only" || word == "not" || word == "and" || word == "or")
Expand Down
6 changes: 3 additions & 3 deletions mode/cypher/cypher.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@
};
var indentUnit = config.indentUnit;
var curPunc;
var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]);
var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor", "like", "ilike", "exists"]);
var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "join", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "reverse", "right", "round", "rtrim", "shortestPath", "sign", "sin", "size", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "toString", "trim", "type", "upper"]);
var preds = wordRegexp(["all", "and", "any", "contains", "exists", "has", "in", "none", "not", "or", "single", "xor"]);
var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "detach", "distinct", "drop", "else", "end", "ends", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "join", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "starts", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
var operatorChars = /[*+\-<>=&|~%^]/;

return {
Expand Down
82 changes: 81 additions & 1 deletion mode/dart/dart.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,101 @@
return obj;
}

function pushInterpolationStack(state) {
(state.interpolationStack || (state.interpolationStack = [])).push(state.tokenize);
}

function popInterpolationStack(state) {
return (state.interpolationStack || (state.interpolationStack = [])).pop();
}

function sizeInterpolationStack(state) {
return state.interpolationStack ? state.interpolationStack.length : 0;
}

CodeMirror.defineMIME("application/dart", {
name: "clike",
keywords: set(keywords),
multiLineStrings: true,
blockKeywords: set(blockKeywords),
builtin: set(builtins),
atoms: set(atoms),
hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);
return "meta";
},

// custom string handling to deal with triple-quoted strings and string interpolation
"'": function(stream, state) {
return tokenString("'", stream, state, false);
},
"\"": function(stream, state) {
return tokenString("\"", stream, state, false);
},
"r": function(stream, state) {
var peek = stream.peek();
if (peek == "'" || peek == "\"") {
return tokenString(stream.next(), stream, state, true);
}
return false;
},

"}": function(_stream, state) {
// "}" is end of interpolation, if interpolation stack is non-empty
if (sizeInterpolationStack(state) > 0) {
state.tokenize = popInterpolationStack(state);
return null;
}
return false;
}
}
});

function tokenString(quote, stream, state, raw) {
var tripleQuoted = false;
if (stream.eat(quote)) {
if (stream.eat(quote)) tripleQuoted = true;
else return "string"; //empty string
}
function tokenStringHelper(stream, state) {
var escaped = false;
while (!stream.eol()) {
if (!raw && !escaped && stream.peek() == "$") {
pushInterpolationStack(state);
state.tokenize = tokenInterpolation;
return "string";
}
var next = stream.next();
if (next == quote && !escaped && (!tripleQuoted || stream.match(quote + quote))) {
state.tokenize = null;
break;
}
escaped = !escaped && next == "\\";
}
return "string";
}
state.tokenize = tokenStringHelper;
return tokenStringHelper(stream, state);
}

function tokenInterpolation(stream, state) {
stream.eat("$");
if (stream.eat("{")) {
// let clike handle the content of ${...},
// we take over again when "}" appears (see hooks).
state.tokenize = null;
} else {
state.tokenize = tokenInterpolationIdentifier;
}
return null;
}

function tokenInterpolationIdentifier(stream, state) {
stream.eatWhile(/[\w_]/);
state.tokenize = popInterpolationStack(state);
return "variable";
}

CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins));

// This is needed to make loading through meta.js work.
Expand Down
17 changes: 13 additions & 4 deletions mode/haxe/haxe.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,20 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
pass.apply(null, arguments);
return true;
}
function inList(name, list) {
for (var v = list; v; v = v.next)
if (v.name == name) return true;
return false;
}
function register(varname) {
var state = cx.state;
if (state.context) {
cx.marked = "def";
for (var v = state.localVars; v; v = v.next)
if (v.name == varname) return;
if (inList(varname, state.localVars)) return;
state.localVars = {name: varname, next: state.localVars};
} else if (state.globalVars) {
if (inList(varname, state.globalVars)) return;
state.globalVars = {name: varname, next: state.globalVars};
}
}

Expand Down Expand Up @@ -380,11 +387,10 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
}

// Interface

return {
startState: function(basecolumn) {
var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"];
return {
var state = {
tokenize: haxeTokenBase,
reAllowed: true,
kwAllowed: true,
Expand All @@ -395,6 +401,9 @@ CodeMirror.defineMode("haxe", function(config, parserConfig) {
context: parserConfig.localVars && {vars: parserConfig.localVars},
indented: 0
};
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
state.globalVars = parserConfig.globalVars;
return state;
},

token: function(stream, state) {
Expand Down
4 changes: 2 additions & 2 deletions mode/htmlmixed/htmlmixed.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@
tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])

function html(stream, state) {
var tagName = state.htmlState.tagName;
var tagInfo = tagName && tags[tagName.toLowerCase()];
var tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase();
var tagInfo = tagName && tags.hasOwnProperty(tagName) && tags[tagName];

var style = htmlMode.token(stream, state.htmlState), modeSpec;

Expand Down
2 changes: 2 additions & 0 deletions mode/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ <h2>Language modes</h2>
<li><a href="asterisk/index.html">Asterisk dialplan</a></li>
<li><a href="brainfuck/index.html">Brainfuck</a></li>
<li><a href="clike/index.html">C, C++, C#</a></li>
<li><a href="clike/index.html">Ceylon</a></li>
<li><a href="clojure/index.html">Clojure</a></li>
<li><a href="css/gss.html">Closure Stylesheets (GSS)</a></li>
<li><a href="cmake/index.html">CMake</a></li>
Expand Down Expand Up @@ -87,6 +88,7 @@ <h2>Language modes</h2>
<li><a href="modelica/index.html">Modelica</a></li>
<li><a href="mumps/index.html">MUMPS</a></li>
<li><a href="nginx/index.html">Nginx</a></li>
<li><a href="nsis/index.html">NSIS</a></li>
<li><a href="ntriples/index.html">NTriples</a></li>
<li><a href="clike/index.html">Objective C</a></li>
<li><a href="mllike/index.html">OCaml</a></li>
Expand Down
25 changes: 20 additions & 5 deletions mode/javascript/javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {

var jsKeywords = {
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
"return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C,
"var": kw("var"), "const": kw("var"), "let": kw("var"),
"async": kw("async"), "function": kw("function"), "catch": kw("catch"),
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
Expand All @@ -56,7 +56,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
"static": kw("static"),

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

for (var attr in tsKeywords) {
Expand Down Expand Up @@ -122,7 +122,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
stream.skipToEnd();
return ret("comment", "comment");
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
readRegexp(stream);
stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
return ret("regexp", "string-2");
Expand Down Expand Up @@ -281,8 +281,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return false;
}
var state = cx.state;
cx.marked = "def";
if (state.context) {
cx.marked = "def";
if (inList(state.localVars)) return;
state.localVars = {name: varname, next: state.localVars};
} else {
Expand Down Expand Up @@ -380,7 +380,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") { return pass(quasi, maybeop); }
if (type == "quasi") return pass(quasi, maybeop);
if (type == "new") return cont(maybeTarget(noComma));
return cont();
}
function maybeexpression(type) {
Expand Down Expand Up @@ -431,6 +432,18 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
findFatArrow(cx.stream, cx.state);
return pass(type == "{" ? statement : expressionNoComma);
}
function maybeTarget(noComma) {
return function(type) {
if (type == ".") return cont(noComma ? targetNoComma : target);
else return pass(noComma ? expressionNoComma : expression);
};
}
function target(_, value) {
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
}
function targetNoComma(_, value) {
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
}
function maybelabel(type) {
if (type == ":") return cont(poplex, statement);
return pass(maybeoperatorComma, expect(";"), poplex);
Expand Down Expand Up @@ -501,6 +514,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function pattern(type, value) {
if (type == "variable") { register(value); return cont(); }
if (type == "spread") return cont(pattern);
if (type == "[") return contCommasep(pattern, "]");
if (type == "{") return contCommasep(proppattern, "}");
}
Expand All @@ -510,6 +524,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return cont(maybeAssign);
}
if (type == "variable") cx.marked = "property";
if (type == "spread") return cont(pattern);
return cont(expect(":"), pattern, maybeAssign);
}
function maybeAssign(_type, value) {
Expand Down
44 changes: 26 additions & 18 deletions mode/javascript/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }

MT("locals",
"[keyword function] [variable foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }");
"[keyword function] [def foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }");

MT("comma-and-binop",
"[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }");
Expand All @@ -18,15 +18,15 @@
"})();");

MT("class_body",
"[keyword class] [variable Foo] {",
"[keyword class] [def Foo] {",
" [property constructor]() {}",
" [property sayName]() {",
" [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];",
" }",
"}");

MT("class",
"[keyword class] [variable Point] [keyword extends] [variable SuperThing] {",
"[keyword class] [def Point] [keyword extends] [variable SuperThing] {",
" [property get] [property prop]() { [keyword return] [number 24]; }",
" [property constructor]([def x], [def y]) {",
" [keyword super]([string 'something']);",
Expand All @@ -35,44 +35,44 @@
"}");

MT("import",
"[keyword function] [variable foo]() {",
"[keyword function] [def foo]() {",
" [keyword import] [def $] [keyword from] [string 'jquery'];",
" [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];",
"}");

MT("const",
"[keyword function] [variable f]() {",
"[keyword function] [def f]() {",
" [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];",
"}");

MT("for/of",
"[keyword for]([keyword let] [variable of] [keyword of] [variable something]) {}");
"[keyword for]([keyword let] [def of] [keyword of] [variable something]) {}");

MT("generator",
"[keyword function*] [variable repeat]([def n]) {",
"[keyword function*] [def repeat]([def n]) {",
" [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])",
" [keyword yield] [variable-2 i];",
"}");

MT("quotedStringAddition",
"[keyword let] [variable f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];");
"[keyword let] [def f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];");

MT("quotedFatArrow",
"[keyword let] [variable f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];");
"[keyword let] [def f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];");

MT("fatArrow",
"[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);",
"[variable a];", // No longer in scope
"[keyword let] [variable f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];",
"[keyword let] [def f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];",
"[variable c];");

MT("spread",
"[keyword function] [variable f]([def a], [meta ...][def b]) {",
"[keyword function] [def f]([def a], [meta ...][def b]) {",
" [variable something]([variable-2 a], [meta ...][variable-2 b]);",
"}");

MT("comprehension",
"[keyword function] [variable f]() {",
"[keyword function] [def f]() {",
" [[([variable x] [operator +] [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];",
" ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] [operator ===] [string 'blue']));",
"}");
Expand All @@ -84,7 +84,7 @@
"[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");

MT("indent_statement",
"[keyword var] [variable x] [operator =] [number 10]",
"[keyword var] [def x] [operator =] [number 10]",
"[variable x] [operator +=] [variable y] [operator +]",
" [atom Infinity]",
"[keyword debugger];");
Expand All @@ -105,14 +105,14 @@
"}");

MT("indent_for",
"[keyword for] ([keyword var] [variable i] [operator =] [number 0];",
"[keyword for] ([keyword var] [def i] [operator =] [number 0];",
" [variable i] [operator <] [number 100];",
" [variable i][operator ++])",
" [variable doSomething]([variable i]);",
"[keyword debugger];");

MT("indent_c_style",
"[keyword function] [variable foo]()",
"[keyword function] [def foo]()",
"{",
" [keyword debugger];",
"}");
Expand Down Expand Up @@ -140,24 +140,32 @@
"[number 2];");

MT("multilinestring",
"[keyword var] [variable x] [operator =] [string 'foo\\]",
"[keyword var] [def x] [operator =] [string 'foo\\]",
"[string bar'];");

MT("scary_regexp",
"[string-2 /foo[[/]]bar/];");

MT("indent_strange_array",
"[keyword var] [variable x] [operator =] [[",
"[keyword var] [def x] [operator =] [[",
" [number 1],,",
" [number 2],",
"]];",
"[number 10];");

MT("param_default",
"[keyword function] [variable foo]([def x] [operator =] [string-2 `foo${][number 10][string-2 }bar`]) {",
"[keyword function] [def foo]([def x] [operator =] [string-2 `foo${][number 10][string-2 }bar`]) {",
" [keyword return] [variable-2 x];",
"}");

MT("new_target",
"[keyword function] [def F]([def target]) {",
" [keyword if] ([variable-2 target] [operator &&] [keyword new].[keyword target].[property name]) {",
" [keyword return] [keyword new]",
" .[keyword target];",
" }",
"}");

var jsonld_mode = CodeMirror.getMode(
{indentUnit: 2},
{name: "javascript", jsonld: true}
Expand Down
89 changes: 0 additions & 89 deletions mode/kotlin/index.html

This file was deleted.

284 changes: 0 additions & 284 deletions mode/kotlin/kotlin.js

This file was deleted.

105 changes: 58 additions & 47 deletions mode/markdown/markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,24 +51,36 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
if (modeCfg.strikethrough === undefined)
modeCfg.strikethrough = false;

// Allow token types to be overridden by user-provided token types.
if (modeCfg.tokenTypeOverrides === undefined)
modeCfg.tokenTypeOverrides = {};

var codeDepth = 0;

var header = 'header'
, code = 'comment'
, quote = 'quote'
, list1 = 'variable-2'
, list2 = 'variable-3'
, list3 = 'keyword'
, hr = 'hr'
, image = 'tag'
, formatting = 'formatting'
, linkinline = 'link'
, linkemail = 'link'
, linktext = 'link'
, linkhref = 'string'
, em = 'em'
, strong = 'strong'
, strikethrough = 'strikethrough';
var tokenTypes = {
header: "header",
code: "comment",
quote: "quote",
list1: "variable-2",
list2: "variable-3",
list3: "keyword",
hr: "hr",
image: "tag",
formatting: "formatting",
linkInline: "link",
linkEmail: "link",
linkText: "link",
linkHref: "string",
em: "em",
strong: "strong",
strikethrough: "strikethrough"
};

for (var tokenType in tokenTypes) {
if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) {
tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType];
}
}

var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/
, ulRE = /^[*\-+]\s+/
Expand Down Expand Up @@ -152,7 +164,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) {
state.indentation -= 4;
state.indentedCode = true;
return code;
return tokenTypes.code;
} else {
return null;
}
Expand All @@ -178,7 +190,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
return switchInline(stream, state, footnoteLink);
} else if (stream.match(hrRE, true)) {
state.hr = true;
return hr;
return tokenTypes.hr;
} else if ((lineIsEmpty(state.prevLine) || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
var listType = null;
if (stream.match(ulRE, true)) {
Expand Down Expand Up @@ -231,7 +243,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
return state.localMode.token(stream, state.localState);
} else {
stream.skipToEnd();
return code;
return tokenTypes.code;
}
}

Expand All @@ -252,22 +264,22 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
var styles = [];

if (state.formatting) {
styles.push(formatting);
styles.push(tokenTypes.formatting);

if (typeof state.formatting === "string") state.formatting = [state.formatting];

for (var i = 0; i < state.formatting.length; i++) {
styles.push(formatting + "-" + state.formatting[i]);
styles.push(tokenTypes.formatting + "-" + state.formatting[i]);

if (state.formatting[i] === "header") {
styles.push(formatting + "-" + state.formatting[i] + "-" + state.header);
styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header);
}

// Add `formatting-quote` and `formatting-quote-#` for blockquotes
// Add `error` instead if the maximum blockquote nesting depth is passed
if (state.formatting[i] === "quote") {
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
styles.push(formatting + "-" + state.formatting[i] + "-" + state.quote);
styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote);
} else {
styles.push("error");
}
Expand All @@ -285,38 +297,36 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
}

if (state.linkHref) {
styles.push(linkhref, "url");
styles.push(tokenTypes.linkHref, "url");
} else { // Only apply inline styles to non-url text
if (state.strong) { styles.push(strong); }
if (state.em) { styles.push(em); }
if (state.strikethrough) { styles.push(strikethrough); }

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

if (state.code) { styles.push(code); }
if (state.strong) { styles.push(tokenTypes.strong); }
if (state.em) { styles.push(tokenTypes.em); }
if (state.strikethrough) { styles.push(tokenTypes.strikethrough); }
if (state.linkText) { styles.push(tokenTypes.linkText); }
if (state.code) { styles.push(tokenTypes.code); }
}

if (state.header) { styles.push(header); styles.push(header + "-" + state.header); }
if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); }

if (state.quote) {
styles.push(quote);
styles.push(tokenTypes.quote);

// Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
styles.push(quote + "-" + state.quote);
styles.push(tokenTypes.quote + "-" + state.quote);
} else {
styles.push(quote + "-" + modeCfg.maxBlockquoteDepth);
styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth);
}
}

if (state.list !== false) {
var listMod = (state.listDepth - 1) % 3;
if (!listMod) {
styles.push(list1);
styles.push(tokenTypes.list1);
} else if (listMod === 1) {
styles.push(list2);
styles.push(tokenTypes.list2);
} else {
styles.push(list3);
styles.push(tokenTypes.list3);
}
}

Expand Down Expand Up @@ -372,7 +382,8 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
stream.next();
if (modeCfg.highlightFormatting) {
var type = getType(state);
return type ? type + " formatting-escape" : "formatting-escape";
var formattingEscape = tokenTypes.formatting + "-escape";
return type ? type + " " + formattingEscape : formattingEscape;
}
}

Expand All @@ -386,7 +397,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
if (stream.match(new RegExp(regex), true)) {
return linkhref;
return tokenTypes.linkHref;
}
}

Expand Down Expand Up @@ -417,7 +428,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
stream.match(/\[[^\]]*\]/);
state.inline = state.f = linkHref;
return image;
return tokenTypes.image;
}

if (ch === '[' && stream.match(/.*\](\(.*\)| ?\[.*\])/, false)) {
Expand All @@ -443,7 +454,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
} else {
type = "";
}
return type + linkinline;
return type + tokenTypes.linkInline;
}

if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
Expand All @@ -455,7 +466,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
} else {
type = "";
}
return type + linkemail;
return type + tokenTypes.linkEmail;
}

if (ch === '<' && stream.match(/^(!--|\w)/, false)) {
Expand Down Expand Up @@ -564,12 +575,12 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
} else {
type = "";
}
return type + linkinline;
return type + tokenTypes.linkInline;
}

stream.match(/^[^>]+/, true);

return linkinline;
return tokenTypes.linkInline;
}

function linkHref(stream, state) {
Expand Down Expand Up @@ -630,7 +641,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {

stream.match(/^[^\]]+/, true);

return linktext;
return tokenTypes.linkText;
}

function footnoteUrl(stream, state) {
Expand All @@ -647,7 +658,7 @@ CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
}
state.f = state.inline = inlineNormal;
return linkhref + " url";
return tokenTypes.linkHref + " url";
}

var savedInlineRE = [];
Expand Down
99 changes: 99 additions & 0 deletions mode/markdown/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,35 @@
function AtxNoSpaceTest(name) { test.mode(name, modeAtxNoSpace, Array.prototype.slice.call(arguments, 1)); }
var modeFenced = CodeMirror.getMode({tabSize: 4}, {name: "markdown", fencedCodeBlocks: true});
function FencedTest(name) { test.mode(name, modeFenced, Array.prototype.slice.call(arguments, 1)); }
var modeOverrideClasses = CodeMirror.getMode({tabsize: 4}, {
name: "markdown",
strikethrough: true,
tokenTypeOverrides: {
"header" : "override-header",
"code" : "override-code",
"quote" : "override-quote",
"list1" : "override-list1",
"list2" : "override-list2",
"list3" : "override-list3",
"hr" : "override-hr",
"image" : "override-image",
"linkInline" : "override-link-inline",
"linkEmail" : "override-link-email",
"linkText" : "override-link-text",
"linkHref" : "override-link-href",
"em" : "override-em",
"strong" : "override-strong",
"strikethrough" : "override-strikethrough"
}});
function TokenTypeOverrideTest(name) { test.mode(name, modeOverrideClasses, Array.prototype.slice.call(arguments, 1)); }
var modeFormattingOverride = CodeMirror.getMode({tabsize: 4}, {
name: "markdown",
highlightFormatting: true,
tokenTypeOverrides: {
"formatting" : "override-formatting"
}});
function FormatTokenTypeOverrideTest(name) { test.mode(name, modeFormattingOverride, Array.prototype.slice.call(arguments, 1)); }


FT("formatting_emAsterisk",
"[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]");
Expand Down Expand Up @@ -774,6 +803,76 @@
"\\",
"[em *foo*]");

// Class override tests
TokenTypeOverrideTest("overrideHeader1",
"[override-header&override-header-1 # Foo]");

TokenTypeOverrideTest("overrideHeader2",
"[override-header&override-header-2 ## Foo]");

TokenTypeOverrideTest("overrideHeader3",
"[override-header&override-header-3 ### Foo]");

TokenTypeOverrideTest("overrideHeader4",
"[override-header&override-header-4 #### Foo]");

TokenTypeOverrideTest("overrideHeader5",
"[override-header&override-header-5 ##### Foo]");

TokenTypeOverrideTest("overrideHeader6",
"[override-header&override-header-6 ###### Foo]");

TokenTypeOverrideTest("overrideCode",
"[override-code `foo`]");

TokenTypeOverrideTest("overrideCodeBlock",
"[override-code ```]",
"[override-code foo]",
"[override-code ```]");

TokenTypeOverrideTest("overrideQuote",
"[override-quote&override-quote-1 > foo]",
"[override-quote&override-quote-1 > bar]");

TokenTypeOverrideTest("overrideQuoteNested",
"[override-quote&override-quote-1 > foo]",
"[override-quote&override-quote-1 >][override-quote&override-quote-2 > bar]",
"[override-quote&override-quote-1 >][override-quote&override-quote-2 >][override-quote&override-quote-3 > baz]");

TokenTypeOverrideTest("overrideLists",
"[override-list1 - foo]",
"",
" [override-list2 + bar]",
"",
" [override-list3 * baz]",
"",
" [override-list1 1. qux]",
"",
" [override-list2 - quux]");

TokenTypeOverrideTest("overrideHr",
"[override-hr * * *]");

TokenTypeOverrideTest("overrideImage",
"[override-image ![[foo]]][override-link-href&url (http://example.com/)]")

TokenTypeOverrideTest("overrideLinkText",
"[override-link-text [[foo]]][override-link-href&url (http://example.com)]");

TokenTypeOverrideTest("overrideLinkEmailAndInline",
"[override-link-email <][override-link-inline foo@example.com>]");

TokenTypeOverrideTest("overrideEm",
"[override-em *foo*]");

TokenTypeOverrideTest("overrideStrong",
"[override-strong **foo**]");

TokenTypeOverrideTest("overrideStrikethrough",
"[override-strikethrough ~~foo~~]");

FormatTokenTypeOverrideTest("overrideFormatting",
"[override-formatting-escape \\*]");

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

Expand Down
5 changes: 3 additions & 2 deletions mode/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
{name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]},
{name: "Jinja2", mime: "null", mode: "jinja2"},
{name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]},
{name: "Kotlin", mime: "text/x-kotlin", mode: "kotlin", ext: ["kt"]},
{name: "Kotlin", mime: "text/x-kotlin", mode: "clike", ext: ["kt"]},
{name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},
{name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},
{name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},
Expand All @@ -83,6 +83,7 @@
{name: "MS SQL", mime: "text/x-mssql", mode: "sql"},
{name: "MySQL", mime: "text/x-mysql", mode: "sql"},
{name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
{name: "NSIS", mime: "text/x-nsis", mode: "nsis", ext: ["nsh", "nsi"]},
{name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]},
{name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"]},
{name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
Expand All @@ -109,7 +110,7 @@
{name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
{name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
{name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},
{name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"]},
{name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"], file: /^PKGBUILD$/},
{name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]},
{name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]},
{name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},
Expand Down
62 changes: 62 additions & 0 deletions mode/nsis/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<!doctype html>

<title>CodeMirror: NSIS mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">

<link rel=stylesheet href=../../lib/codemirror.css>
<script src=../../lib/codemirror.js></script>
<script src="../../addon/mode/simple.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src=nsis.js></script>
<style type=text/css>
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>

<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">NSIS</a>
</ul>
</div>

<article>
<h2>NSIS mode</h2>


<textarea id=code>
; This is a comment
!ifdef ERROR
!error "Something went wrong"
!endif

OutFile "demo.exe"
RequestExecutionLevel user

!include "LogicLib.nsh"

Section -mandatory
${If} 1 > 0
MessageBox MB_OK "Hello world"
${EndIf}
SectionEnd
</textarea>

<script>
var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
mode: 'nsis',
indentWithTabs: true,
smartIndent: true,
lineNumbers: true,
matchBrackets: true
});
</script>

<p><strong>MIME types defined:</strong> <code>text/x-nsis</code>.</p>
</article>
63 changes: 63 additions & 0 deletions mode/nsis/nsis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE

// Author: Jan T. Sott (http://github.com/idleberg)

(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../../addon/mode/simple"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";

CodeMirror.defineSimpleMode("nsis",{
start:[
// Numbers
{regex: /(?:[+-]?)(?:0x[\d,a-f]+)|(?:0o[0-7]+)|(?:0b[0,1]+)|(?:\d+.?\d*)/, token: "number"},
// Compile Time Commands
{regex: /(?:\!(include|addincludedir|addplugindir|appendfile|cd|delfile|echo|error|execute|packhdr|finalize|getdllversion|system|tempfile|warning|verbose|define|undef|insertmacro|makensis|searchparse|searchreplace))\b/, token: "keyword"},
// Conditional Compilation
{regex: /(?:\!(if(?:n?def)?|ifmacron?def|macro))\b/, token: "keyword", indent: true},
{regex: /(?:\!(else|endif|macroend))\b/, token: "keyword", dedent: true},
// Runtime Commands
{regex: /(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetLabelAddress|GetTempFileName|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|IntCmp|IntCmpU|IntFmt|IntOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetPluginUnload|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegStr|WriteUninstaller|XPStyle)\b/, token: "keyword"},
{regex: /\b(?:Function|PageEx|Section(?:Group)?)\b/, token: "keyword", indent: true},
{regex: /\b(?:(Function|PageEx|Section(?:Group)?)End)\b/, token: "keyword", dedent: true},
// Options
{regex: /\b(?:ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HIDDEN|HKCC|HKCR|HKCU|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM|HKPD|HKU|IDABORT|IDCANCEL|IDD_DIR|IDD_INST|IDD_INSTFILES|IDD_LICENSE|IDD_SELCOM|IDD_UNINST|IDD_VERIFY|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|MB_YESNOCANCEL|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SW_HIDE|SW_SHOWDEFAULT|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED|SW_SHOWNORMAL|SYSTEM|TEMPORARY)\b/, token: "atom"},
{regex: /\b(?:admin|all|auto|both|bottom|bzip2|components|current|custom|directory|force|hide|highest|ifdiff|ifnewer|instfiles|lastused|leave|left|license|listonly|lzma|nevershow|none|normal|notset|right|show|silent|silentlog|textonly|top|try|un\.components|un\.custom|un\.directory|un\.instfiles|un\.license|uninstConfirm|user|Win10|Win7|Win8|WinVista|zlib)\b/, token: "builtin"},

// LogicLib
{regex: /\$\{(?:End(If|Unless|While)|Loop(?:Until)|Next)\}/, token: "variable-2", dedent: true},
{regex: /\$\{(?:Do(Until|While)|Else(?:If(?:Not)?)?|For(?:Each)?|(?:(?:And|Else|Or)?If(?:Cmd|Not|Then)?|Unless)|While)\}/, token: "variable-2", indent: true},

// Line Comment
{regex: /(#|;).*/, token: "comment"},
// Block Comment
{regex: /\/\*/, token: "comment", next: "comment"},
// Operator
{regex: /[-+\/*=<>!]+/, token: "operator"},
// Variable
{regex: /\$[\w]+/, token: "variable"},
// Constant
{regex: /\${[\w]+}/,token: "variable-2"},
// Language String
{regex: /\$\([\w]+\)/,token: "variable-3"}
],
comment: [
{regex: /.*?\*\//, token: "comment", next: "start"},
{regex: /.*/, token: "comment"}
],
meta: {
electricInput: /^\s*((Function|PageEx|Section|Section(Group)?)End|(\!(endif|macroend))|\$\{(End(If|Unless|While)|Loop(Until)|Next)\})$/,
blockCommentStart: "/*",
blockCommentEnd: "*/",
lineComment: ["#", ";"]
}
});

CodeMirror.defineMIME("text/x-nsis", "nsis");
});
26 changes: 17 additions & 9 deletions mode/rpm/rpm.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ CodeMirror.defineMIME("text/x-rpm-changes", "rpm-changes");
// Quick and dirty spec file highlighting

CodeMirror.defineMode("rpm-spec", function() {
var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;
var arch = /^(i386|i586|i686|x86_64|ppc64le|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;

var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/;
var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
var preamble = /^[a-zA-Z0-9()]+:/;
var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pretrans|posttrans|pre|post|triggerin|triggerun|verifyscript|check|triggerpostun|triggerprein|trigger)/;
var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros
var control_flow_simple = /^%(else|endif)/; // rpm control flow macros
var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros
Expand All @@ -55,8 +55,8 @@ CodeMirror.defineMode("rpm-spec", function() {
if (ch == "#") { stream.skipToEnd(); return "comment"; }

if (stream.sol()) {
if (stream.match(preamble)) { return "preamble"; }
if (stream.match(section)) { return "section"; }
if (stream.match(preamble)) { return "header"; }
if (stream.match(section)) { return "atom"; }
}

if (stream.match(/^\$\w+/)) { return "def"; } // Variables like '$RPM_BUILD_ROOT'
Expand All @@ -73,21 +73,29 @@ CodeMirror.defineMode("rpm-spec", function() {
if (stream.eol()) { state.controlFlow = false; }
}

if (stream.match(arch)) { return "number"; }
if (stream.match(arch)) {
if (stream.eol()) { state.controlFlow = false; }
return "number";
}

// Macros like '%make_install' or '%attr(0775,root,root)'
if (stream.match(/^%[\w]+/)) {
if (stream.match(/^\(/)) { state.macroParameters = true; }
return "macro";
return "keyword";
}
if (state.macroParameters) {
if (stream.match(/^\d+/)) { return "number";}
if (stream.match(/^\)/)) {
state.macroParameters = false;
return "macro";
return "keyword";
}
}
if (stream.match(/^%\{\??[\w \-]+\}/)) { return "macro"; } // Macros like '%{defined fedora}'

// Macros like '%{defined fedora}'
if (stream.match(/^%\{\??[\w \-\:\!]+\}/)) {
if (stream.eol()) { state.controlFlow = false; }
return "def";
}

//TODO: Include bash script sub-parser (CodeMirror supports that)
stream.next();
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codemirror",
"version":"5.7.0",
"version":"5.8.0",
"main": "lib/codemirror.js",
"description": "In-browser code editing made bearable",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion test/comment_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ namespace = "comment_";

test("indented", "javascript", function(cm) {
cm.lineComment(Pos(1, 0), Pos(2), {indent: true});
}, simpleProg, "function foo() {\n // return bar;\n // }");
}, simpleProg, "function foo() {\n// return bar;\n// }");

test("singleEmptyLine", "javascript", function(cm) {
cm.setCursor(1);
Expand Down
2 changes: 1 addition & 1 deletion theme/abcdef.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@
.cm-s-abcdef span.cm-attribute { color: #DDFF00; }
.cm-s-abcdef span.cm-error { color: #FF0000; }
.cm-s-abcdef span.cm-header { color: aquamarine; font-weight: bold; }
.cm-s-abcdef span.cm-link { color: blue; }
.cm-s-abcdef span.cm-link { color: blueviolet; }

.cm-s-abcdef .CodeMirror-activeline-background { background: #314151; }
2 changes: 1 addition & 1 deletion theme/base16-dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Name: Base16 Default Dark
Author: Chris Kempson (http://chriskempson.com)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/
Expand Down
2 changes: 1 addition & 1 deletion theme/base16-light.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Name: Base16 Default Light
Author: Chris Kempson (http://chriskempson.com)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/
Expand Down
34 changes: 34 additions & 0 deletions theme/bespin.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Name: Bespin
Author: Mozilla / Jan T. Sott
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/

.cm-s-bespin.CodeMirror {background: #28211c; color: #9d9b97;}
.cm-s-bespin div.CodeMirror-selected {background: #36312e !important;}
.cm-s-bespin .CodeMirror-gutters {background: #28211c; border-right: 0px;}
.cm-s-bespin .CodeMirror-linenumber {color: #666666;}
.cm-s-bespin .CodeMirror-cursor {border-left: 1px solid #797977 !important;}

.cm-s-bespin span.cm-comment {color: #937121;}
.cm-s-bespin span.cm-atom {color: #9b859d;}
.cm-s-bespin span.cm-number {color: #9b859d;}

.cm-s-bespin span.cm-property, .cm-s-bespin span.cm-attribute {color: #54be0d;}
.cm-s-bespin span.cm-keyword {color: #cf6a4c;}
.cm-s-bespin span.cm-string {color: #f9ee98;}

.cm-s-bespin span.cm-variable {color: #54be0d;}
.cm-s-bespin span.cm-variable-2 {color: #5ea6ea;}
.cm-s-bespin span.cm-def {color: #cf7d34;}
.cm-s-bespin span.cm-error {background: #cf6a4c; color: #797977;}
.cm-s-bespin span.cm-bracket {color: #9d9b97;}
.cm-s-bespin span.cm-tag {color: #cf6a4c;}
.cm-s-bespin span.cm-link {color: #9b859d;}

.cm-s-bespin .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
.cm-s-bespin .CodeMirror-activeline-background { background: #404040; }
34 changes: 34 additions & 0 deletions theme/hopscotch.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Name: Hopscotch
Author: Jan T. Sott
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/

.cm-s-hopscotch.CodeMirror {background: #322931; color: #d5d3d5;}
.cm-s-hopscotch div.CodeMirror-selected {background: #433b42 !important;}
.cm-s-hopscotch .CodeMirror-gutters {background: #322931; border-right: 0px;}
.cm-s-hopscotch .CodeMirror-linenumber {color: #797379;}
.cm-s-hopscotch .CodeMirror-cursor {border-left: 1px solid #989498 !important;}

.cm-s-hopscotch span.cm-comment {color: #b33508;}
.cm-s-hopscotch span.cm-atom {color: #c85e7c;}
.cm-s-hopscotch span.cm-number {color: #c85e7c;}

.cm-s-hopscotch span.cm-property, .cm-s-hopscotch span.cm-attribute {color: #8fc13e;}
.cm-s-hopscotch span.cm-keyword {color: #dd464c;}
.cm-s-hopscotch span.cm-string {color: #fdcc59;}

.cm-s-hopscotch span.cm-variable {color: #8fc13e;}
.cm-s-hopscotch span.cm-variable-2 {color: #1290bf;}
.cm-s-hopscotch span.cm-def {color: #fd8b19;}
.cm-s-hopscotch span.cm-error {background: #dd464c; color: #989498;}
.cm-s-hopscotch span.cm-bracket {color: #d5d3d5;}
.cm-s-hopscotch span.cm-tag {color: #dd464c;}
.cm-s-hopscotch span.cm-link {color: #c85e7c;}

.cm-s-hopscotch .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
.cm-s-hopscotch .CodeMirror-activeline-background { background: #302020; }
34 changes: 34 additions & 0 deletions theme/isotope.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Name: Isotope
Author: David Desandro / Jan T. Sott
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/

.cm-s-isotope.CodeMirror {background: #000000; color: #e0e0e0;}
.cm-s-isotope div.CodeMirror-selected {background: #404040 !important;}
.cm-s-isotope .CodeMirror-gutters {background: #000000; border-right: 0px;}
.cm-s-isotope .CodeMirror-linenumber {color: #808080;}
.cm-s-isotope .CodeMirror-cursor {border-left: 1px solid #c0c0c0 !important;}

.cm-s-isotope span.cm-comment {color: #3300ff;}
.cm-s-isotope span.cm-atom {color: #cc00ff;}
.cm-s-isotope span.cm-number {color: #cc00ff;}

.cm-s-isotope span.cm-property, .cm-s-isotope span.cm-attribute {color: #33ff00;}
.cm-s-isotope span.cm-keyword {color: #ff0000;}
.cm-s-isotope span.cm-string {color: #ff0099;}

.cm-s-isotope span.cm-variable {color: #33ff00;}
.cm-s-isotope span.cm-variable-2 {color: #0066ff;}
.cm-s-isotope span.cm-def {color: #ff9900;}
.cm-s-isotope span.cm-error {background: #ff0000; color: #c0c0c0;}
.cm-s-isotope span.cm-bracket {color: #e0e0e0;}
.cm-s-isotope span.cm-tag {color: #ff0000;}
.cm-s-isotope span.cm-link {color: #cc00ff;}

.cm-s-isotope .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
.cm-s-isotope .CodeMirror-activeline-background { background: #202020; }
28 changes: 14 additions & 14 deletions theme/liquibyte.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
line-height: 1.2em;
font-size: 1em;
}
.CodeMirror-focused .cm-matchhighlight {
.cm-s-liquibyte .CodeMirror-focused .cm-matchhighlight {
text-decoration: underline;
text-decoration-color: #0f0;
text-decoration-style: wavy;
}
.cm-trailingspace {
.cm-s-liquibyte .cm-trailingspace {
text-decoration: line-through;
text-decoration-color: #f00;
text-decoration-style: dotted;
}
.cm-tab {
.cm-s-liquibyte .cm-tab {
text-decoration: line-through;
text-decoration-color: #404040;
text-decoration-style: dotted;
Expand Down Expand Up @@ -54,42 +54,42 @@
.cm-s-liquibyte .CodeMirror-activeline-background { background-color: rgba(0, 255, 0, 0.15); }

/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket { color: #0f0; font-weight: bold; }
div.CodeMirror span.CodeMirror-nonmatchingbracket { color: #f00; font-weight: bold; }
.cm-s-liquibyte .CodeMirror span.CodeMirror-matchingbracket { color: #0f0; font-weight: bold; }
.cm-s-liquibyte .CodeMirror span.CodeMirror-nonmatchingbracket { color: #f00; font-weight: bold; }
.CodeMirror-matchingtag { background-color: rgba(150, 255, 0, .3); }
/* Scrollbars */
/* Simple */
div.CodeMirror-simplescroll-horizontal div:hover, div.CodeMirror-simplescroll-vertical div:hover {
.cm-s-liquibyte div.CodeMirror-simplescroll-horizontal div:hover, div.CodeMirror-simplescroll-vertical div:hover {
background-color: rgba(80, 80, 80, .7);
}
div.CodeMirror-simplescroll-horizontal div, div.CodeMirror-simplescroll-vertical div {
.cm-s-liquibyte div.CodeMirror-simplescroll-horizontal div, div.CodeMirror-simplescroll-vertical div {
background-color: rgba(80, 80, 80, .3);
border: 1px solid #404040;
border-radius: 5px;
}
div.CodeMirror-simplescroll-vertical div {
.cm-s-liquibyte div.CodeMirror-simplescroll-vertical div {
border-top: 1px solid #404040;
border-bottom: 1px solid #404040;
}
div.CodeMirror-simplescroll-horizontal div {
.cm-s-liquibyte div.CodeMirror-simplescroll-horizontal div {
border-left: 1px solid #404040;
border-right: 1px solid #404040;
}
div.CodeMirror-simplescroll-vertical {
.cm-s-liquibyte div.CodeMirror-simplescroll-vertical {
background-color: #262626;
}
div.CodeMirror-simplescroll-horizontal {
.cm-s-liquibyte div.CodeMirror-simplescroll-horizontal {
background-color: #262626;
border-top: 1px solid #404040;
}
/* Overlay */
div.CodeMirror-overlayscroll-horizontal div, div.CodeMirror-overlayscroll-vertical div {
.cm-s-liquibyte div.CodeMirror-overlayscroll-horizontal div, div.CodeMirror-overlayscroll-vertical div {
background-color: #404040;
border-radius: 5px;
}
div.CodeMirror-overlayscroll-vertical div {
.cm-s-liquibyte div.CodeMirror-overlayscroll-vertical div {
border: 1px solid #404040;
}
div.CodeMirror-overlayscroll-horizontal div {
.cm-s-liquibyte div.CodeMirror-overlayscroll-horizontal div {
border: 1px solid #404040;
}
Loading