20 changes: 15 additions & 5 deletions addon/search/searchcursor.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,26 @@
if (!newMatch) break;
match = newMatch;
start = match.index;
cutOff = match.index + 1;
cutOff = match.index + (match[0].length || 1);
if (cutOff == line.length) break;
}
var matchLen = (match && match[0].length) || 0;
if (!matchLen) {
if (start == 0 && line.length == 0) {match = undefined;}
else if (start != doc.getLine(pos.line).length) {
matchLen++;
}
}
} else {
query.lastIndex = pos.ch;
var line = doc.getLine(pos.line), match = query.exec(line),
start = match && match.index;
var line = doc.getLine(pos.line), match = query.exec(line);
var matchLen = (match && match[0].length) || 0;
var start = match && match.index;
if (start + matchLen != line.length && !matchLen) matchLen = 1;
}
if (match && match[0])
if (match && matchLen)
return {from: Pos(pos.line, start),
to: Pos(pos.line, start + match[0].length),
to: Pos(pos.line, start + matchLen),
match: match};
};
} else { // String query
Expand Down
12 changes: 6 additions & 6 deletions addon/selection/active-line.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@
} else if (!val && prev) {
cm.off("cursorActivity", updateActiveLine);
clearActiveLine(cm);
delete cm._activeLine;
delete cm.state.activeLine;
}
});

function clearActiveLine(cm) {
if ("_activeLine" in cm) {
cm.removeLineClass(cm._activeLine, "wrap", WRAP_CLASS);
cm.removeLineClass(cm._activeLine, "background", BACK_CLASS);
if ("activeLine" in cm.state) {
cm.removeLineClass(cm.state.activeLine, "wrap", WRAP_CLASS);
cm.removeLineClass(cm.state.activeLine, "background", BACK_CLASS);
}
}

function updateActiveLine(cm) {
var line = cm.getLineHandle(cm.getCursor().line);
if (cm._activeLine == line) return;
if (cm.state.activeLine == line) return;
clearActiveLine(cm);
cm.addLineClass(line, "wrap", WRAP_CLASS);
cm.addLineClass(line, "background", BACK_CLASS);
cm._activeLine = line;
cm.state.activeLine = line;
}
})();
104 changes: 89 additions & 15 deletions addon/selection/mark-selection.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,108 @@
// Because sometimes you need to mark the selected *text*.
//
// Adds an option 'styleSelectedText' which, when enabled, gives
// selected text the CSS class "CodeMirror-selectedtext".
// selected text the CSS class given as option value, or
// "CodeMirror-selectedtext" when the value is not a string.

(function() {
"use strict";

CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
var prev = old && old != CodeMirror.Init;
if (val && !prev) {
updateSelectedText(cm);
cm.on("cursorActivity", updateSelectedText);
cm.state.markedSelection = [];
cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext";
reset(cm);
cm.on("cursorActivity", onCursorActivity);
cm.on("change", onChange);
} else if (!val && prev) {
cm.off("cursorActivity", updateSelectedText);
clearSelectedText(cm);
delete cm._selectionMark;
cm.off("cursorActivity", onCursorActivity);
cm.off("change", onChange);
clear(cm);
cm.state.markedSelection = cm.state.markedSelectionStyle = null;
}
});

function clearSelectedText(cm) {
if (cm._selectionMark) cm._selectionMark.clear();
function onCursorActivity(cm) {
cm.operation(function() { update(cm); });
}

function updateSelectedText(cm) {
clearSelectedText(cm);
function onChange(cm) {
if (cm.state.markedSelection.length)
cm.operation(function() { clear(cm); });
}

var CHUNK_SIZE = 8;
var Pos = CodeMirror.Pos;

function cmp(pos1, pos2) {
return pos1.line - pos2.line || pos1.ch - pos2.ch;
}

function coverRange(cm, from, to, addAt) {
if (cmp(from, to) == 0) return;
var array = cm.state.markedSelection;
var cls = cm.state.markedSelectionStyle;
for (var line = from.line;;) {
var start = line == from.line ? from : Pos(line, 0);
var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line;
var end = atEnd ? to : Pos(endLine, 0);
var mark = cm.markText(start, end, {className: cls});
if (addAt == null) array.push(mark);
else array.splice(addAt++, 0, mark);
if (atEnd) break;
line = endLine;
}
}

if (cm.somethingSelected())
cm._selectionMark = cm.markText(cm.getCursor("start"), cm.getCursor("end"),
{className: "CodeMirror-selectedtext"});
else
cm._selectionMark = null;
function clear(cm) {
var array = cm.state.markedSelection;
for (var i = 0; i < array.length; ++i) array[i].clear();
array.length = 0;
}

function reset(cm) {
clear(cm);
var from = cm.getCursor("start"), to = cm.getCursor("end");
coverRange(cm, from, to);
}

function update(cm) {
var from = cm.getCursor("start"), to = cm.getCursor("end");
if (cmp(from, to) == 0) return clear(cm);

var array = cm.state.markedSelection;
if (!array.length) return coverRange(cm, from, to);

var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE ||
cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
return reset(cm);

while (cmp(from, coverStart.from) > 0) {
array.shift().clear();
coverStart = array[0].find();
}
if (cmp(from, coverStart.from) < 0) {
if (coverStart.to.line - from.line < CHUNK_SIZE) {
array.shift().clear();
coverRange(cm, from, coverStart.to, 0);
} else {
coverRange(cm, from, coverStart.from, 0);
}
}

while (cmp(to, coverEnd.to) < 0) {
array.pop().clear();
coverEnd = array[array.length - 1].find();
}
if (cmp(to, coverEnd.to) > 0) {
if (to.line - coverEnd.from.line < CHUNK_SIZE) {
array.pop().clear();
coverRange(cm, coverEnd.from, to);
} else {
coverRange(cm, coverEnd.to, to);
}
}
}
})();
7 changes: 4 additions & 3 deletions bin/compress
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ function help(ok) {
process.exit(ok ? 0 : 1);
}

var local = null, args = null, files = [], blob = "";
var local = null, args = [], extraArgs = null, files = [], blob = "";

for (var i = 2; i < process.argv.length; ++i) {
var arg = process.argv[i];
if (arg == "--local" && i + 1 < process.argv.length) {
var parts = process.argv[++i].split(/\s+/);
local = parts[0];
args = parts.slice(1);
extraArgs = parts.slice(1);
if (!extraArgs.length) extraArgs = ["-c", "-m"];
} else if (arg == "--help") {
help(true);
} else if (arg[0] != "-") {
Expand Down Expand Up @@ -73,7 +74,7 @@ if (files.length) {
}

if (local) {
require("child_process").spawn(local, args, {stdio: ["ignore", process.stdout, process.stderr]});
require("child_process").spawn(local, args.concat(extraArgs), {stdio: ["ignore", process.stdout, process.stderr]});
} else {
var data = new Buffer("js_code=" + require("querystring").escape(blob), "utf8");
var req = require("http").request({
Expand Down
61 changes: 61 additions & 0 deletions bin/source-highlight
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env node

// Simple command-line code highlighting tool. Reads code from stdin,
// spits html to stdout. For example:
//
// echo 'function foo(a) { return a; }' | bin/source-highlight -s javascript
// bin/source-highlight -s

var fs = require("fs");

CodeMirror = require("../addon/runmode/runmode.node.js");
require("../mode/meta.js");

var sPos = process.argv.indexOf("-s");
if (sPos == -1 || sPos == process.argv.length - 1) {
console.error("Usage: source-highlight -s language");
process.exit(1);
}
var lang = process.argv[sPos + 1].toLowerCase(), modeName = lang;
CodeMirror.modeInfo.forEach(function(info) {
if (info.mime == lang) {
modeName = info.mode;
} else if (info.name.toLowerCase() == lang) {
modeName = info.mode;
lang = info.mime;
}
});

function ensureMode(name) {
if (CodeMirror.modes[name] || name == "null") return;
try {
require("../mode/" + name + "/" + name + ".js");
} catch(e) {
console.error("Could not load mode " + name + ".");
process.exit(1);
}
var obj = CodeMirror.modes[name];
if (obj.dependencies) obj.dependencies.forEach(ensureMode);
}
ensureMode(modeName);

function esc(str) {
return str.replace(/[<&]/, function(ch) { return ch == "&" ? "&amp;" : "&lt;"; });
}

var code = fs.readFileSync("/dev/stdin", "utf8");
var curStyle = null, accum = "";
function flush() {
if (curStyle) process.stdout.write("<span class=\"" + curStyle.replace(/(^|\s+)/g, "$1cm-") + "\">" + esc(accum) + "</span>");
else process.stdout.write(esc(accum));
}

CodeMirror.runMode(code, lang, function(text, style) {
if (style != curStyle) {
flush();
curStyle = style; accum = text;
} else {
accum += text;
}
});
flush();
3 changes: 3 additions & 0 deletions 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=3.13.0;f=">3.13</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>
Expand Down Expand Up @@ -73,6 +74,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<option value="http://codemirror.net/mode/apl/apl.js">apl.js</option>
<option value="http://codemirror.net/mode/clike/clike.js">clike.js</option>
<option value="http://codemirror.net/mode/clojure/clojure.js">clojure.js</option>
<option value="http://codemirror.net/mode/cobol/cobol.js">cobol.js</option>
<option value="http://codemirror.net/mode/coffeescript/coffeescript.js">coffeescript.js</option>
<option value="http://codemirror.net/mode/commonlisp/commonlisp.js">commonlisp.js</option>
<option value="http://codemirror.net/mode/css/css.js">css.js</option>
Expand All @@ -84,6 +86,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<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/haml/haml.js">haml.js</option>
<option value="http://codemirror.net/mode/haskell/haskell.js">haskell.js</option>
<option value="http://codemirror.net/mode/haxe/haxe.js">haxe.js</option>
<option value="http://codemirror.net/mode/htmlembedded/htmlembedded.js">htmlembedded.js</option>
Expand Down
156 changes: 133 additions & 23 deletions doc/manual.html

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions doc/modes.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="../mode/asterisk/index.html">Asterisk dialplan</a></li>
<li><a href="../mode/clike/index.html">C, C++, C#</a></li>
<li><a href="../mode/clojure/index.html">Clojure</a></li>
<li><a href="../mode/cobol/index.html">COBOL</a></li>
<li><a href="../mode/coffeescript/index.html">CoffeeScript</a></li>
<li><a href="../mode/commonlisp/index.html">Common Lisp</a></li>
<li><a href="../mode/css/index.html">CSS</a></li>
Expand All @@ -37,6 +38,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<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/haml/index.html">HAML</a></li>
<li><a href="../mode/haskell/index.html">Haskell</a></li>
<li><a href="../mode/haxe/index.html">Haxe</a></li>
<li><a href="../mode/htmlembedded/index.html">HTML embedded scripts</a></li>
Expand Down
28 changes: 28 additions & 0 deletions doc/oldrelease.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,34 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
</pre>
</div>

<p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-3.0rc1.zip">Version 3.0, release candidate 1</a>:</p>

<ul class="rel-note">
<li>New theme: <a href="../demo/theme.html?solarized%20light">Solarized</a>.</li>
<li>Introduce <a href="manual.html#addLineClass"><code>addLineClass</code></a>
and <a href="manual.html#removeLineClass"><code>removeLineClass</code></a>,
drop <code>setLineClass</code>.</li>
<li>Add a <em>lot</em> of
new <a href="manual.html#markText">options for marked text</a>
(read-only, atomic, collapsed, widget replacement).</li>
<li>Remove the old code folding interface in favour of these new ranges.</li>
<li>Add <a href="manual.html#isClean"><code>isClean</code></a>/<a href="manual.html#markClean"><code>markClean</code></a> methods.</li>
<li>Remove <code>compoundChange</code> method, use better undo-event-combining heuristic.</li>
<li>Improve scrolling performance smoothness.</li>
<li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.0beta2...v3.0rc1">list of patches</a>.</li>
</ul>

<p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-2.35.zip">Version 2.35</a>:</p>

<ul class="rel-note">
<li>New (sub) mode: <a href="../mode/javascript/typescript.html">TypeScript</a>.</li>
<li>Don't overwrite (insert key) when pasting.</li>
<li>Fix several bugs in <a href="manual.html#markText"><code>markText</code></a>/undo interaction.</li>
<li>Better indentation of JavaScript code without semicolons.</li>
<li>Add <a href="manual.html#defineInitHook"><code>defineInitHook</code></a> function.</li>
<li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v2.34...v2.35">list of patches</a>.</li>
</ul>

<p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-3.0beta2.zip">Version 3.0, beta 2</a>:</p>

<ul class="rel-note">
Expand Down
11 changes: 11 additions & 0 deletions doc/realworld.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,21 @@ <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://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>
<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://clickhelp.co/">ClickHelp</a> (technical writing tool)</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="https://github.com/angelozerr/CodeMirror-Eclipse">CodeMirror Eclipse</a> (embed CM in Eclipse)</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>
<li><a href="http://www.crunchzilla.com/code-monster">Code Monster</a> & <a href="http://www.crunchzilla.com/code-maven">Code Maven</a> (learning environment)</li>
<li><a href="http://codepen.io">Codepen</a> (gallery of animations)</li>
<li><a href="http://sasstwo.codeschool.com/levels/1/challenges/1">Code School</a> (online tech learning environment)</li>
<li><a href="http://code-snippets.bungeshea.com/">Code Snippets</a> (WordPress snippet management plugin)</li>
<li><a href="http://antonmi.github.io/code_together/">Code together</a> (collaborative editing)</li>
<li><a href="http://codev.it/">Codev</a> (collaborative IDE)</li>
<li><a href="http://ot.substance.io/demo/">Collaborative CodeMirror demo</a> (CodeMirror + operational transforms)</li>
<li><a href="http://www.communitycodecamp.com/">Community Code Camp</a> (code snippet sharing)</li>
Expand All @@ -54,13 +58,16 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<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>
<li><a href="http://web.uvic.ca/~siefkenj/graphit/graphit.html">Graphit</a> (function graphing)</li>
<li><a href="http://www.handcraft2.com/">Handcraft 2</a> (HTML prototyping)</li>
<li><a href="http://try.haxe.org">Haxe</a> (Haxe Playground) </li>
<li><a href="http://haxpad.com/">HaxPad</a> (editor for Win RT)</li>
<li><a href="http://megafonweblab.github.com/histone-javascript/">Histone template engine playground</a></li>
<li><a href="http://icecoder.net">ICEcoder</a> (web IDE)</li>
<li><a href="http://www.janvas.com/">Janvas</a> (vector graphics editor)</li>
<li><a href="http://extensions.joomla.org/extensions/edition/editors/8723">Joomla plugin</a></li>
<li><a href="http://jqfundamentals.com/">jQuery fundamentals</a> (interactive tutorial)</li>
<li><a href="http://jsbin.com">jsbin.com</a> (JS playground)</li>
<li><a href="http://jsfiddle.com">jsfiddle.com</a> (another JS playground)</li>
<li><a href="http://www.jshint.com/">JSHint</a> (JS linter)</li>
<li><a href="http://jumpseller.com/">Jumpseller</a> (online store builder)</li>
<li><a href="http://kl1p.com/cmtest/1">kl1p</a> (paste service)</li>
Expand All @@ -69,7 +76,9 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="http://www.iunbug.com/mihtool">MIHTool</a> (iOS web-app debugging tool)</li>
<li><a href="http://mongo-mapreduce-webbrowser.opensagres.cloudbees.net/">Mongo MapReduce WebBrowser</a></li>
<li><a href="https://www.my2ndgeneration.com/">My2ndGeneration</a> (social coding)</li>
<li><a href="http://www.navigatecms.com">Navigate CMS</a></li>
<li><a href="https://notex.ch">NoTex</a> (rST authoring)</li>
<li><a href="http://oakoutliner.com">Oak</a> (online outliner)</li>
<li><a href="http://clrhome.org/asm/">ORG</a> (z80 assembly IDE)</li>
<li><a href="https://github.com/mamacdon/orion-codemirror">Orion-CodeMirror integration</a> (running CodeMirror modes in Orion)</li>
<li><a href="http://paperjs.org/">Paper.js</a> (graphics scripting)</li>
Expand All @@ -81,6 +90,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="https://www.realtime.io/">RealTime.io</a> (Internet-of-Things infrastructure)</li>
<li><a href="http://www.sketchpatch.net/labs/livecodelabIntro.html">sketchPatch Livecodelab</a></li>
<li><a href="http://www.skulpt.org/">Skulpt</a> (in-browser Python environment)</li>
<li><a href="http://snippets.pro/">Snippets.pro</a> (code snippet sharing)</li>
<li><a href="http://www.solidshops.com/">SolidShops</a> (hosted e-commerce platform)</li>
<li><a href="http://sqlfiddle.com">SQLFiddle</a> (SQL playground)</li>
<li><a href="https://thefiletree.com">The File Tree</a> (collab editor)</li>
Expand All @@ -89,6 +99,7 @@ <h1><span class="logo-braces">{ }</span> <a href="http://codemirror.net/">CodeMi
<li><a href="http://blog.englard.net/post/39608000629/codeintumblr">Tumblr code highlighting shim</a></li>
<li><a href="http://turbopy.com/">TurboPY</a> (web publishing framework)</li>
<li><a href="http://cruise.eecs.uottawa.ca/umpleonline/">UmpleOnline</a> (model-oriented programming tool)</li>
<li><a href="https://upsource.jetbrains.com/#idea/view/923f30395f2603cd9f42a32bcafd13b6c28de0ff/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java">Upsource</a> (code viewer)</li>
<li><a href="http://webglplayground.net/">WebGL playground</a></li>
<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>
Expand Down
77 changes: 30 additions & 47 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -120,28 +120,29 @@ <h2 style="margin-top: 0">Usage demos:</h2>
<h2>Real-world uses:</h2>

<ul>
<li><a href="http://jsbin.com">jsbin.com</a> (JS playground)</li>
<li><a href="http://www.chris-granger.com/2012/04/12/light-table---a-new-ide-concept/">Light Table</a> (experimental IDE)</li>
<li><a href="http://brackets.io">Adobe Brackets</a> (code editor)</li>
<li><a href="http://www.mergely.com/">Mergely</a> (interactive diffing)</li>
<li><a href="http://www.chris-granger.com/2012/04/12/light-table---a-new-ide-concept/">Light Table</a></li>
<li><a href="http://brackets.io">Adobe Brackets</a></li>
<li><a href="http://jsbin.com">jsbin.com</a></li>
<li><a href="http://jsfiddle.com">jsfiddle.com</a></li>
<li><a href="http://blog.bitbucket.org/2013/05/14/edit-your-code-in-the-cloud-with-bitbucket/">Bitbucket</a></li>
<li><a href="https://script.google.com/">Google Apps Script</a></li>
<li><a href="https://github.com/github/android">GitHub's Android app</a></li>
<li><a href="http://eloquentjavascript.net/chapter1.html">Eloquent JavaScript</a> (book)</li>
<li><a href="http://emmet.io">Emmet</a> (fast XML editing)</li>
<li><a href="http://paperjs.org/">Paper.js</a> (graphics scripting)</li>
<li><a href="http://codev.it/">Codev</a> (collaborative IDE)</li>
<li><a href="http://enjalot.com/tributary/2636296/sinwaves.js">Tributary</a> (augmented editing)</li>
<li><a href="http://prose.io/">Prose.io</a> (github content editor)</li>
<li><a href="http://www.wescheme.org/">WeScheme</a> (learning tool)</li>
<li><a href="http://eloquentjavascript.net/chapter1.html">Eloquent JavaScript</a></li>
<li><a href="http://emmet.io">Emmet</a></li>
<li><a href="http://prose.io/">Prose.io</a></li>
<li><a href="https://upsource.jetbrains.com/#idea/view/923f30395f2603cd9f42a32bcafd13b6c28de0ff/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ReplaceAbstractClassInstanceByMapIntention.java">Upsource</a></li>
<li><a href="http://paperjs.org/">Paper.js</a></li>
<li><a href="http://codev.it/">Codev</a></li>
<li><a href="http://enjalot.com/tributary/2636296/sinwaves.js">Tributary</a></li>
<li><a href="http://www.wescheme.org/">WeScheme</a></li>
<li><a href="http://www.mergely.com/">Mergely</a></li>
<li><a href="http://webglplayground.net/">WebGL playground</a></li>
<li><a href="http://ql.io/">ql.io</a> (http API query helper)</li>
<li><a href="https://thefiletree.com">The File Tree</a> (collab editor)</li>
<li><a href="http://www.jshint.com/">JSHint</a> (JS linter)</li>
<li><a href="http://sqlfiddle.com">SQLFiddle</a> (SQL playground)</li>
<li><a href="http://try.haxe.org">Try Haxe</a> (Haxe Playground) </li>
<li><a href="http://cssdeck.com/">CSSDeck</a> (CSS showcase)</li>
<li><a href="https://thefiletree.com">The File Tree</a></li>
<li><a href="http://www.jshint.com/">JSHint</a></li>
<li><a href="http://sqlfiddle.com">SQLFiddle</a></li>
<li><a href="http://cssdeck.com/">CSSDeck</a></li>
<li><a href="http://www.sketchpatch.net/labs/livecodelabIntro.html">sketchPatch Livecodelab</a></li>
<li><a href="https://notex.ch">NoTex</a> (rST authoring)</li>
<li><a href="https://notex.ch">NoTex</a></li>
<li><a href="https://github.com/github/android">GitHub's Android app</a></li>
<li><a href="doc/realworld.html">More...</a></li>
</ul>

Expand Down Expand Up @@ -286,6 +287,16 @@ <h2>Reading material</h2>

<h2 id=releases>Releases</h2>

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

<ul class="rel-note">
<li>New modes: <a href="mode/cobol/index.html">COBOL</a> and <a href="mode/haml/index.html">HAML</a>.</li>
<li>New options: <a href="doc/manual.html#option_cursorScrollMargin"><code>cursorScrollMargin</code></a> and <a href="doc/manual.html#option_coverGutterNextToScrollbar"><code>coverGutterNextToScrollbar</code></a>.</li>
<li>New addon: <a href="doc/manual.html#addon_comment">commenting</a>.</li>
<li>More features added to the <a href="demo/vim.html">Vim keymap</a>.</li>
<li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.12...3.13.0">list of patches</a>.</li>
</ul>

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

<ul class="rel-note">
Expand Down Expand Up @@ -444,34 +455,6 @@ <h2 id=releases>Releases</h2>
<li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v2.35...v2.36">list of patches</a>.</li>
</ul>

<p class="rel">20-11-2012: <a href="http://codemirror.net/codemirror-3.0rc1.zip">Version 3.0, release candidate 1</a>:</p>

<ul class="rel-note">
<li>New theme: <a href="demo/theme.html?solarized%20light">Solarized</a>.</li>
<li>Introduce <a href="doc/manual.html#addLineClass"><code>addLineClass</code></a>
and <a href="doc/manual.html#removeLineClass"><code>removeLineClass</code></a>,
drop <code>setLineClass</code>.</li>
<li>Add a <em>lot</em> of
new <a href="doc/manual.html#markText">options for marked text</a>
(read-only, atomic, collapsed, widget replacement).</li>
<li>Remove the old code folding interface in favour of these new ranges.</li>
<li>Add <a href="doc/manual.html#isClean"><code>isClean</code></a>/<a href="doc/manual.html#markClean"><code>markClean</code></a> methods.</li>
<li>Remove <code>compoundChange</code> method, use better undo-event-combining heuristic.</li>
<li>Improve scrolling performance smoothness.</li>
<li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v3.0beta2...v3.0rc1">list of patches</a>.</li>
</ul>

<p class="rel">22-10-2012: <a href="http://codemirror.net/codemirror-2.35.zip">Version 2.35</a>:</p>

<ul class="rel-note">
<li>New (sub) mode: <a href="mode/javascript/typescript.html">TypeScript</a>.</li>
<li>Don't overwrite (insert key) when pasting.</li>
<li>Fix several bugs in <a href="doc/manual.html#markText"><code>markText</code></a>/undo interaction.</li>
<li>Better indentation of JavaScript code without semicolons.</li>
<li>Add <a href="doc/manual.html#defineInitHook"><code>defineInitHook</code></a> function.</li>
<li>Full <a href="https://github.com/marijnh/CodeMirror/compare/v2.34...v2.35">list of patches</a>.</li>
</ul>

<p><a href="doc/oldrelease.html">Older releases...</a></p>

</div></div>
Expand Down
638 changes: 451 additions & 187 deletions keymap/vim.js

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions lib/codemirror.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
padding: 0 4px; /* Horizontal padding of content */
}

.CodeMirror-scrollbar-filler {
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}

Expand All @@ -28,6 +28,7 @@
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
Expand Down Expand Up @@ -124,7 +125,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
Expand All @@ -141,16 +142,18 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
z-index: 6;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}

.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
height: 100%;
padding-bottom: 30px;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
padding-bottom: 30px;
margin-bottom: -32px;
Expand Down
282 changes: 167 additions & 115 deletions lib/codemirror.js

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions mode/clike/clike.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,15 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
var closing = firstChar == ctx.type;
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
else if (dontAlignCalls && ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
else if (ctx.align) return ctx.column + (closing ? 0 : 1);
else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
else return ctx.indented + (closing ? 0 : indentUnit);
},

electricChars: "{}"
electricChars: "{}",
blockCommentStart: "/*",
blockCommentEnd: "*/",
lineComment: "//"
};
});

Expand Down
4 changes: 3 additions & 1 deletion mode/clojure/clojure.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,9 @@ CodeMirror.defineMode("clojure", function () {
indent: function (state) {
if (state.indentStack == null) return state.indentation;
return state.indentStack.indent;
}
},

lineComment: ";;"
};
});

Expand Down
240 changes: 240 additions & 0 deletions mode/cobol/cobol.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/**
* Author: Gautam Mehta
* Branched from CodeMirror's Scheme mode
*/
CodeMirror.defineMode("cobol", function () {
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header",
COBOLLINENUM = "def", PERIOD = "link";
function makeKeywords(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES ");
var keywords = makeKeywords(
"ACCEPT ACCESS ACQUIRE ADD ADDRESS " +
"ADVANCING AFTER ALIAS ALL ALPHABET " +
"ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " +
"ALSO ALTER ALTERNATE AND ANY " +
"ARE AREA AREAS ARITHMETIC ASCENDING " +
"ASSIGN AT ATTRIBUTE AUTHOR AUTO " +
"AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " +
"B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " +
"BEFORE BELL BINARY BIT BITS " +
"BLANK BLINK BLOCK BOOLEAN BOTTOM " +
"BY CALL CANCEL CD CF " +
"CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " +
"CLOSE COBOL CODE CODE-SET COL " +
"COLLATING COLUMN COMMA COMMIT COMMITMENT " +
"COMMON COMMUNICATION COMP COMP-0 COMP-1 " +
"COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " +
"COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " +
"COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " +
"COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " +
"CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " +
"CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " +
"CONVERTING COPY CORR CORRESPONDING COUNT " +
"CRT CRT-UNDER CURRENCY CURRENT CURSOR " +
"DATA DATE DATE-COMPILED DATE-WRITTEN DAY " +
"DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " +
"DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " +
"DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " +
"DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " +
"DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " +
"DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " +
"DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " +
"DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " +
"DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " +
"DOWN DROP DUPLICATE DUPLICATES DYNAMIC " +
"EBCDIC EGI EJECT ELSE EMI " +
"EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " +
"END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " +
"END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " +
"END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " +
"END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " +
"END-UNSTRING END-WRITE END-XML ENTER ENTRY " +
"ENVIRONMENT EOP EQUAL EQUALS ERASE " +
"ERROR ESI EVALUATE EVERY EXCEEDS " +
"EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " +
"EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " +
"FILE-STREAM FILES FILLER FINAL FIND " +
"FINISH FIRST FOOTING FOR FOREGROUND-COLOR " +
"FOREGROUND-COLOUR FORMAT FREE FROM FULL " +
"FUNCTION GENERATE GET GIVING GLOBAL " +
"GO GOBACK GREATER GROUP HEADING " +
"HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " +
"ID IDENTIFICATION IF IN INDEX " +
"INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " +
"INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " +
"INDIC INDICATE INDICATOR INDICATORS INITIAL " +
"INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " +
"INSTALLATION INTO INVALID INVOKE IS " +
"JUST JUSTIFIED KANJI KEEP KEY " +
"LABEL LAST LD LEADING LEFT " +
"LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " +
"LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " +
"LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " +
"LOCALE LOCALLY LOCK " +
"MEMBER MEMORY MERGE MESSAGE METACLASS " +
"MODE MODIFIED MODIFY MODULES MOVE " +
"MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " +
"NEXT NO NO-ECHO NONE NOT " +
"NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " +
"NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " +
"OF OFF OMITTED ON ONLY " +
"OPEN OPTIONAL OR ORDER ORGANIZATION " +
"OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " +
"PADDING PAGE PAGE-COUNTER PARSE PERFORM " +
"PF PH PIC PICTURE PLUS " +
"POINTER POSITION POSITIVE PREFIX PRESENT " +
"PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " +
"PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " +
"PROMPT PROTECTED PURGE QUEUE QUOTE " +
"QUOTES RANDOM RD READ READY " +
"REALM RECEIVE RECONNECT RECORD RECORD-NAME " +
"RECORDS RECURSIVE REDEFINES REEL REFERENCE " +
"REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " +
"REMAINDER REMOVAL RENAMES REPEATED REPLACE " +
"REPLACING REPORT REPORTING REPORTS REPOSITORY " +
"REQUIRED RERUN RESERVE RESET RETAINING " +
"RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " +
"REVERSED REWIND REWRITE RF RH " +
"RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " +
"RUN SAME SCREEN SD SEARCH " +
"SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " +
"SELECT SEND SENTENCE SEPARATE SEQUENCE " +
"SEQUENTIAL SET SHARED SIGN SIZE " +
"SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " +
"SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " +
"SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " +
"START STARTING STATUS STOP STORE " +
"STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " +
"SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " +
"SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " +
"TABLE TALLYING TAPE TENANT TERMINAL " +
"TERMINATE TEST TEXT THAN THEN " +
"THROUGH THRU TIME TIMES TITLE " +
"TO TOP TRAILING TRAILING-SIGN TRANSACTION " +
"TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " +
"UNSTRING UNTIL UP UPDATE UPON " +
"USAGE USAGE-MODE USE USING VALID " +
"VALIDATE VALUE VALUES VARYING VLR " +
"WAIT WHEN WHEN-COMPILED WITH WITHIN " +
"WORDS WORKING-STORAGE WRITE XML XML-CODE " +
"XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " );

var builtins = makeKeywords("- * ** / + < <= = > >= ");
var tests = {
digit: /\d/,
digit_or_colon: /[\d:]/,
hex: /[0-9a-f]/i,
sign: /[+-]/,
exponent: /e/i,
keyword_char: /[^\s\(\[\;\)\]]/,
symbol: /[\w*+\-]/
};
function isNumber(ch, stream){
// hex
if ( ch === '0' && stream.eat(/x/i) ) {
stream.eatWhile(tests.hex);
return true;
}
// leading sign
if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {
stream.eat(tests.sign);
ch = stream.next();
}
if ( tests.digit.test(ch) ) {
stream.eat(ch);
stream.eatWhile(tests.digit);
if ( '.' == stream.peek()) {
stream.eat('.');
stream.eatWhile(tests.digit);
}
if ( stream.eat(tests.exponent) ) {
stream.eat(tests.sign);
stream.eatWhile(tests.digit);
}
return true;
}
return false;
}
return {
startState: function () {
return {
indentStack: null,
indentation: 0,
mode: false
};
},
token: function (stream, state) {
if (state.indentStack == null && stream.sol()) {
// update indentation, but only if indentStack is empty
state.indentation = 6 ; //stream.indentation();
}
// skip spaces
if (stream.eatSpace()) {
return null;
}
var returnType = null;
switch(state.mode){
case "string": // multi-line string parsing mode
var next = false;
while ((next = stream.next()) != null) {
if (next == "\"" || next == "\'") {
state.mode = false;
break;
}
}
returnType = STRING; // continue on in string mode
break;
default: // default parsing mode
var ch = stream.next();
var col = stream.column();
if (col >= 0 && col <= 5) {
returnType = COBOLLINENUM;
} else if (col >= 72 && col <= 79) {
stream.skipToEnd();
returnType = MODTAG;
} else if (ch == "*" && col == 6) { // comment
stream.skipToEnd(); // rest of the line is a comment
returnType = COMMENT;
} else if (ch == "\"" || ch == "\'") {
state.mode = "string";
returnType = STRING;
} else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
returnType = ATOM;
} else if (ch == ".") {
returnType = PERIOD;
} else if (isNumber(ch,stream)){
returnType = NUMBER;
} else {
if (stream.current().match(tests.symbol)) {
while (col < 71) {
if (stream.eat(tests.symbol) === undefined) {
break;
} else {
col++;
}
}
}
if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {
returnType = KEYWORD;
} else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) {
returnType = BUILTIN;
} else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) {
returnType = ATOM;
} else returnType = null;
}
}
return returnType;
},
indent: function (state) {
if (state.indentStack == null) return state.indentation;
return state.indentStack.indent;
}
};
});

CodeMirror.defineMIME("text/x-cobol", "cobol");
195 changes: 195 additions & 0 deletions mode/cobol/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CodeMirror: COBOL mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="cobol.js"></script>
<link rel="stylesheet" href="../../theme/neat.css">
<link rel="stylesheet" href="../../theme/elegant.css">
<link rel="stylesheet" href="../../theme/erlang-dark.css">
<link rel="stylesheet" href="../../theme/night.css">
<link rel="stylesheet" href="../../theme/monokai.css">
<link rel="stylesheet" href="../../theme/cobalt.css">
<link rel="stylesheet" href="../../theme/eclipse.css">
<link rel="stylesheet" href="../../theme/rubyblue.css">
<link rel="stylesheet" href="../../theme/lesser-dark.css">
<link rel="stylesheet" href="../../theme/xq-dark.css">
<link rel="stylesheet" href="../../theme/xq-light.css">
<link rel="stylesheet" href="../../theme/ambiance.css">
<link rel="stylesheet" href="../../theme/blackboard.css">
<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">
<link rel="stylesheet" href="../../addon/dialog/dialog.css">
<script src="../../addon/selection/active-line.js"></script>
<script src="../../addon/search/search.js"></script>
<script src="../../addon/dialog/dialog.js"></script>
<script src="../../addon/search/searchcursor.js"></script>
<style>
.CodeMirror {
border: 1px solid #eee;
font-size : 20px;
height : auto !important;
}
.CodeMirror-activeline-background {background: #555555 !important;}
</style>
</head>
<body>
<p> Select Theme <select onchange="selectTheme()" id="selectTheme">
<option>default</option>
<option>ambiance</option>
<option>blackboard</option>
<option>cobalt</option>
<option>eclipse</option>
<option>elegant</option>
<option>erlang-dark</option>
<option>lesser-dark</option>
<option>midnight</option>
<option>monokai</option>
<option>neat</option>
<option>night</option>
<option>rubyblue</option>
<option>solarized dark</option>
<option>solarized light</option>
<option selected>twilight</option>
<option>vibrant-ink</option>
<option>xq-dark</option>
<option>xq-light</option>
</select> Select Font Size <select onchange="selectFontsize()" id="selectFontSize">
<option value="13px">13px</option>
<option value="14px">14px</option>
<option value="16px">16px</option>
<option value="18px">18px</option>
<option value="20px" selected="selected">20px</option>
<option value="24px">24px</option>
<option value="26px">26px</option>
<option value="28px">28px</option>
<option value="30px">30px</option>
<option value="32px">32px</option>
<option value="34px">34px</option>
<option value="36px">36px</option>
</select>
<label for="checkBoxReadOnly">Read-only</label>
<input type="checkbox" id="checkBoxReadOnly" onchange="selectReadOnly()">
<label for="id_tabToIndentSpace">Insert Spaces on Tab</label>
<input type="checkbox" id="id_tabToIndentSpace" onchange="tabToIndentSpace()">
</p>
<textarea id="code" name="code">
---------1---------2---------3---------4---------5---------6---------7---------8
12345678911234567892123456789312345678941234567895123456789612345678971234567898
000010 IDENTIFICATION DIVISION. MODTGHERE
000020 PROGRAM-ID. SAMPLE.
000030 AUTHOR. TEST SAM.
000040 DATE-WRITTEN. 5 February 2013
000041
000042* A sample program just to show the form.
000043* The program copies its input to the output,
000044* and counts the number of records.
000045* At the end this number is printed.
000046
000050 ENVIRONMENT DIVISION.
000060 INPUT-OUTPUT SECTION.
000070 FILE-CONTROL.
000080 SELECT STUDENT-FILE ASSIGN TO SYSIN
000090 ORGANIZATION IS LINE SEQUENTIAL.
000100 SELECT PRINT-FILE ASSIGN TO SYSOUT
000110 ORGANIZATION IS LINE SEQUENTIAL.
000120
000130 DATA DIVISION.
000140 FILE SECTION.
000150 FD STUDENT-FILE
000160 RECORD CONTAINS 43 CHARACTERS
000170 DATA RECORD IS STUDENT-IN.
000180 01 STUDENT-IN PIC X(43).
000190
000200 FD PRINT-FILE
000210 RECORD CONTAINS 80 CHARACTERS
000220 DATA RECORD IS PRINT-LINE.
000230 01 PRINT-LINE PIC X(80).
000240
000250 WORKING-STORAGE SECTION.
000260 01 DATA-REMAINS-SWITCH PIC X(2) VALUE SPACES.
000261 01 RECORDS-WRITTEN PIC 99.
000270
000280 01 DETAIL-LINE.
000290 05 FILLER PIC X(7) VALUE SPACES.
000300 05 RECORD-IMAGE PIC X(43).
000310 05 FILLER PIC X(30) VALUE SPACES.
000311
000312 01 SUMMARY-LINE.
000313 05 FILLER PIC X(7) VALUE SPACES.
000314 05 TOTAL-READ PIC 99.
000315 05 FILLER PIC X VALUE SPACE.
000316 05 FILLER PIC X(17)
000317 VALUE 'Records were read'.
000318 05 FILLER PIC X(53) VALUE SPACES.
000319
000320 PROCEDURE DIVISION.
000321
000330 PREPARE-SENIOR-REPORT.
000340 OPEN INPUT STUDENT-FILE
000350 OUTPUT PRINT-FILE.
000351 MOVE ZERO TO RECORDS-WRITTEN.
000360 READ STUDENT-FILE
000370 AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
000380 END-READ.
000390 PERFORM PROCESS-RECORDS
000410 UNTIL DATA-REMAINS-SWITCH = 'NO'.
000411 PERFORM PRINT-SUMMARY.
000420 CLOSE STUDENT-FILE
000430 PRINT-FILE.
000440 STOP RUN.
000450
000460 PROCESS-RECORDS.
000470 MOVE STUDENT-IN TO RECORD-IMAGE.
000480 MOVE DETAIL-LINE TO PRINT-LINE.
000490 WRITE PRINT-LINE.
000500 ADD 1 TO RECORDS-WRITTEN.
000510 READ STUDENT-FILE
000520 AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
000530 END-READ.
000540
000550 PRINT-SUMMARY.
000560 MOVE RECORDS-WRITTEN TO TOTAL-READ.
000570 MOVE SUMMARY-LINE TO PRINT-LINE.
000571 WRITE PRINT-LINE.
000572
000580
</textarea>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-cobol",
theme : "twilight",
styleActiveLine: true,
showCursorWhenSelecting : true,
});
function selectTheme() {
var themeInput = document.getElementById("selectTheme");
var theme = themeInput.options[themeInput.selectedIndex].innerHTML;
editor.setOption("theme", theme);
}
function selectFontsize() {
var fontSizeInput = document.getElementById("selectFontSize");
var fontSize = fontSizeInput.options[fontSizeInput.selectedIndex].innerHTML;
editor.getWrapperElement().style["font-size"] = fontSize;
editor.refresh();
}
function selectReadOnly() {
editor.setOption("readOnly", document.getElementById("checkBoxReadOnly").checked);
}
function tabToIndentSpace() {
if (document.getElementById("id_tabToIndentSpace").checked) {
editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection(" ", "end"); }});
} else {
editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection(" ", "end"); }});
}
}
</script>
</body>
</html>
3 changes: 2 additions & 1 deletion mode/coffeescript/coffeescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,9 @@ CodeMirror.defineMode('coffeescript', function(conf) {
}

return state.scopes[0].offset;
}
},

lineComment: "#"
};
return external;
});
Expand Down
6 changes: 5 additions & 1 deletion mode/commonlisp/commonlisp.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ CodeMirror.defineMode("commonlisp", function (config) {
indent: function (state, _textAfter) {
var i = state.ctx.indentTo;
return typeof i == "number" ? i : state.ctx.start + 1;
}
},

lineComment: ";;",
blockCommentStart: "#|",
blockCommentEnd: "|#"
};
});

Expand Down
87 changes: 63 additions & 24 deletions mode/css/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,26 +165,27 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
if (type == "variable-definition") state.stack.push("propertyValue");
return "variable-2";
} else if (style == "property") {
if (context == "propertyValue"){
if (valueKeywords[stream.current()]) {
var word = stream.current().toLowerCase();
if (context == "propertyValue") {
if (valueKeywords.hasOwnProperty(word)) {
style = "string-2";
} else if (colorKeywords[stream.current()]) {
} else if (colorKeywords.hasOwnProperty(word)) {
style = "keyword";
} else {
style = "variable-2";
}
} else if (context == "rule") {
if (!propertyKeywords[stream.current()]) {
if (!propertyKeywords.hasOwnProperty(word)) {
style += " error";
}
} else if (context == "block") {
// if a value is present in both property, value, or color, the order
// of preference is property -> color -> value
if (propertyKeywords[stream.current()]) {
if (propertyKeywords.hasOwnProperty(word)) {
style = "property";
} else if (colorKeywords[stream.current()]) {
} else if (colorKeywords.hasOwnProperty(word)) {
style = "keyword";
} else if (valueKeywords[stream.current()]) {
} else if (valueKeywords.hasOwnProperty(word)) {
style = "string-2";
} else {
style = "tag";
Expand All @@ -194,42 +195,42 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
} else if (context == "@media") {
if (atMediaTypes[stream.current()]) {
style = "attribute"; // Known attribute
} else if (/^(only|not)$/i.test(stream.current())) {
} else if (/^(only|not)$/.test(word)) {
style = "keyword";
} else if (stream.current().toLowerCase() == "and") {
} else if (word == "and") {
style = "error"; // "and" is only allowed in @mediaType
} else if (atMediaFeatures[stream.current()]) {
} else if (atMediaFeatures.hasOwnProperty(word)) {
style = "error"; // Known property, should be in @mediaType(
} else {
// Unknown, expecting keyword or attribute, assuming attribute
style = "attribute error";
}
} else if (context == "@mediaType") {
if (atMediaTypes[stream.current()]) {
if (atMediaTypes.hasOwnProperty(word)) {
style = "attribute";
} else if (stream.current().toLowerCase() == "and") {
} else if (word == "and") {
style = "operator";
} else if (/^(only|not)$/i.test(stream.current())) {
} else if (/^(only|not)$/.test(word)) {
style = "error"; // Only allowed in @media
} else if (atMediaFeatures[stream.current()]) {
style = "error"; // Known property, should be in parentheses
} else {
// Unknown attribute or property, but expecting property (preceded
// by "and"). Should be in parentheses
style = "error";
}
} else if (context == "@mediaType(") {
if (propertyKeywords[stream.current()]) {
if (propertyKeywords.hasOwnProperty(word)) {
// do nothing, remains "property"
} else if (atMediaTypes[stream.current()]) {
} else if (atMediaTypes.hasOwnProperty(word)) {
style = "error"; // Known property, should be in parentheses
} else if (stream.current().toLowerCase() == "and") {
} else if (word == "and") {
style = "operator";
} else if (/^(only|not)$/i.test(stream.current())) {
} else if (/^(only|not)$/.test(word)) {
style = "error"; // Only allowed in @media
} else {
style += " error";
}
} else if (context == "@import") {
style = "tag";
} else {
style = "error";
}
Expand Down Expand Up @@ -266,13 +267,15 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
}
else if (type == "interpolation") state.stack.push("interpolation");
else if (type == "@media") state.stack.push("@media");
else if (type == "@import") state.stack.push("@import");
else if (context == "@media" && /\b(keyword|attribute)\b/.test(style))
state.stack.push("@mediaType");
else if (context == "@mediaType" && stream.current() == ",") state.stack.pop();
else if (context == "@mediaType" && type == "(") state.stack.push("@mediaType(");
else if (context == "@mediaType(" && type == ")") state.stack.pop();
else if ((context == "rule" || context == "block") && type == ":") state.stack.push("propertyValue");
else if (context == "propertyValue" && type == ";") state.stack.pop();
else if (context == "@import" && type == ";") state.stack.pop();
return style;
},

Expand All @@ -283,7 +286,9 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
return state.baseIndent + n * indentUnit;
},

electricChars: "}"
electricChars: "}",
blockCommentStart: "/*",
blockCommentEnd: "*/"
};
});

Expand Down Expand Up @@ -387,12 +392,46 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
"vertical-align", "visibility", "voice-balance", "voice-duration",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
"word-spacing", "word-wrap", "z-index"
"word-spacing", "word-wrap", "z-index",
// SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"color-interpolation", "color-interpolation-filters", "color-profile",
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
"marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
"glyph-orientation-vertical", "kerning", "text-anchor", "writing-mode"
]);

var colorKeywords = keySet([
"black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia",
"green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua"
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
"gold", "goldenrod", "gray", "green", "greenyellow", "honeydew",
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
"purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon",
"sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
"whitesmoke", "yellow", "yellowgreen"
]);

var valueKeywords = keySet([
Expand Down Expand Up @@ -475,7 +514,7 @@ CodeMirror.defineMode("css-base", function(config, parserConfig) {
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
"vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
"visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider",
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
"window", "windowframe", "windowtext", "x-large", "x-small", "xor",
"xx-large", "xx-small"
]);
Expand Down
5 changes: 3 additions & 2 deletions mode/erlang/erlang.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,9 @@ CodeMirror.defineMode("erlang", function(cmCfg) {

indent:
function(state, textAfter) {
// console.log(state.tokenStack);
return myIndent(state,textAfter);
}
},

lineComment: "%"
};
});
6 changes: 5 additions & 1 deletion mode/gas/gas.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ CodeMirror.defineMode("gas", function(_config, parserConfig) {
return style;
}
}
}
},

lineComment: lineCommentStartSymbol,
blockCommentStart: "/*",
blockCommentEnd: "*/"
};
});
5 changes: 4 additions & 1 deletion mode/go/go.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,10 @@ CodeMirror.defineMode("go", function(config) {
else return ctx.indented + (closing ? 0 : indentUnit);
},

electricChars: "{}:"
electricChars: "{}:",
blockCommentStart: "/*",
blockCommentEnd: "*/",
lineComment: "//"
};
});

Expand Down
153 changes: 153 additions & 0 deletions mode/haml/haml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
(function() {
"use strict";

// full haml mode. This handled embeded ruby and html fragments too
CodeMirror.defineMode("haml", function(config) {
var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});
var rubyMode = CodeMirror.getMode(config, "ruby");

function rubyInQuote(endQuote) {
return function(stream, state) {
var ch = stream.peek();
if (ch == endQuote && state.rubyState.tokenize.length == 1) {
// step out of ruby context as it seems to complete processing all the braces
stream.next();
state.tokenize = html;
return "closeAttributeTag";
} else {
return ruby(stream, state);
}
};
}

function ruby(stream, state) {
if (stream.match("-#")) {
stream.skipToEnd();
return "comment";
}
return rubyMode.token(stream, state.rubyState);
}

function html(stream, state) {
var ch = stream.peek();

// handle haml declarations. All declarations that cant be handled here
// will be passed to html mode
if (state.previousToken.style == "comment" ) {
if (state.indented > state.previousToken.indented) {
stream.skipToEnd();
return "commentLine";
}
}

if (state.startOfLine) {
if (ch == "!" && stream.match("!!")) {
stream.skipToEnd();
return "tag";
} else if (stream.match(/^%[\w:#\.]+=/)) {
state.tokenize = ruby;
return "hamlTag";
} else if (stream.match(/^%[\w:]+/)) {
return "hamlTag";
} else if (ch == "/" ) {
stream.skipToEnd();
return "comment";
}
}

if (state.startOfLine || state.previousToken.style == "hamlTag") {
if ( ch == "#" || ch == ".") {
stream.match(/[\w-#\.]*/);
return "hamlAttribute";
}
}

// donot handle --> as valid ruby, make it HTML close comment instead
if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) {
state.tokenize = ruby;
return null;
}

if (state.previousToken.style == "hamlTag" ||
state.previousToken.style == "closeAttributeTag" ||
state.previousToken.style == "hamlAttribute") {
if (ch == "(") {
state.tokenize = rubyInQuote(")");
return null;
} else if (ch == "{") {
state.tokenize = rubyInQuote("}");
return null;
}
}

return htmlMode.token(stream, state.htmlState);
}

return {
// default to html mode
startState: function() {
var htmlState = htmlMode.startState();
var rubyState = rubyMode.startState();
return {
htmlState: htmlState,
rubyState: rubyState,
indented: 0,
previousToken: { style: null, indented: 0},
tokenize: html
};
},

copyState: function(state) {
return {
htmlState : CodeMirror.copyState(htmlMode, state.htmlState),
rubyState: CodeMirror.copyState(rubyMode, state.rubyState),
indented: state.indented,
previousToken: state.previousToken,
tokenize: state.tokenize
};
},

token: function(stream, state) {
if (stream.sol()) {
state.indented = stream.indentation();
state.startOfLine = true;
}
if (stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
state.startOfLine = false;
// dont record comment line as we only want to measure comment line with
// the opening comment block
if (style && style != "commentLine") {
state.previousToken = { style: style, indented: state.indented };
}
// if current state is ruby and the previous token is not `,` reset the
// tokenize to html
if (stream.eol() && state.tokenize == ruby) {
stream.backUp(1);
var ch = stream.peek();
stream.next();
if (ch && ch != ",") {
state.tokenize = html;
}
}
// reprocess some of the specific style tag when finish setting previousToken
if (style == "hamlTag") {
style = "tag";
} else if (style == "commentLine") {
style = "comment";
} else if (style == "hamlAttribute") {
style = "attribute";
} else if (style == "closeAttributeTag") {
style = null;
}
return style;
},

indent: function(state) {
return state.indented;
}
};
}, "htmlmixed", "ruby");

CodeMirror.defineMIME("text/x-haml", "haml");
})();
67 changes: 67 additions & 0 deletions mode/haml/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CodeMirror: HAML mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../xml/xml.js"></script>
<script src="../htmlmixed/htmlmixed.js"></script>
<script src="../javascript/javascript.js"></script>
<script src="../ruby/ruby.js"></script>
<script src="haml.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style>
<link rel="stylesheet" href="../../doc/docs.css">
</head>
<body>
<h1>CodeMirror: HAML mode</h1>
<form><textarea id="code" name="code">
!!!
#content
.left.column(title="title"){:href => "/hello", :test => "#{hello}_#{world}"}
<!-- This is a comment -->
%h2 Welcome to our site!
%p= puts "HAML MODE"
.right.column
= render :partial => "sidebar"

.container
.row
.span8
%h1.title= @page_title
%p.title= @page_title
%p
/
The same as HTML comment
Hello multiline comment

-# haml comment
This wont be displayed
nor will this
Date/Time:
- now = DateTime.now
%strong= now
- if now > DateTime.parse("December 31, 2006")
= "Happy new " + "year!"

%title
= @title
\= @title
<h1>Title</h1>
<h1 title="HELLO">
Title
</h1>
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
mode: "text/x-haml"
});
</script>

<p><strong>MIME types defined:</strong> <code>text/x-haml</code>.</p>

<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#haml_*">normal</a>, <a href="../../test/index.html#verbose,haml_*">verbose</a>.</p>

</body>
</html>
94 changes: 94 additions & 0 deletions mode/haml/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
(function() {
var mode = CodeMirror.getMode({tabSize: 4}, "haml");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }

// Requires at least one media query
MT("elementName",
"[tag %h1] Hey There");

MT("oneElementPerLine",
"[tag %h1] Hey There %h2");

MT("idSelector",
"[tag %h1][attribute #test] Hey There");

MT("classSelector",
"[tag %h1][attribute .hello] Hey There");

MT("docType",
"[tag !!! XML]");

MT("comment",
"[comment / Hello WORLD]");

MT("notComment",
"[tag %h1] This is not a / comment ");

MT("attributes",
"[tag %a]([variable title][operator =][string \"test\"]){[atom :title] [operator =>] [string \"test\"]}");

MT("htmlCode",
"[tag <h1>]Title[tag </h1>]");

MT("rubyBlock",
"[operator =][variable-2 @item]");

MT("selectorRubyBlock",
"[tag %a.selector=] [variable-2 @item]");

MT("nestedRubyBlock",
"[tag %a]",
" [operator =][variable puts] [string \"test\"]");

MT("multilinePlaintext",
"[tag %p]",
" Hello,",
" World");

MT("multilineRuby",
"[tag %p]",
" [comment -# this is a comment]",
" [comment and this is a comment too]",
" Date/Time",
" [operator -] [variable now] [operator =] [tag DateTime][operator .][variable now]",
" [tag %strong=] [variable now]",
" [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][variable parse]([string \"December 31, 2006\"])",
" [operator =][string \"Happy\"]",
" [operator =][string \"Belated\"]",
" [operator =][string \"Birthday\"]");

MT("multilineComment",
"[comment /]",
" [comment Multiline]",
" [comment Comment]");

MT("hamlComment",
"[comment -# this is a comment]");

MT("multilineHamlComment",
"[comment -# this is a comment]",
" [comment and this is a comment too]");

MT("multilineHTMLComment",
"[comment <!--]",
" [comment what a comment]",
" [comment -->]");

MT("hamlAfterRubyTag",
"[attribute .block]",
" [tag %strong=] [variable now]",
" [attribute .test]",
" [operator =][variable now]",
" [attribute .right]");

MT("stretchedRuby",
"[operator =] [variable puts] [string \"Hello\"],",
" [string \"World\"]");

MT("interpolationInHashAttribute",
//"[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test");
"[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test");

MT("interpolationInHTMLAttribute",
"[tag %div]([variable title][operator =][string \"#{][variable test][string }_#{][variable ting]()[string }\"]) Test");
})();
6 changes: 5 additions & 1 deletion mode/haskell/haskell.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,11 @@ CodeMirror.defineMode("haskell", function() {
var t = state.f(stream, function(s) { state.f = s; });
var w = stream.current();
return (w in wellKnownWords) ? wellKnownWords[w] : t;
}
},

blockCommentStart: "{-",
blockCommentEnd: "-}",
lineComment: "--"
};

});
Expand Down
4 changes: 3 additions & 1 deletion mode/javascript/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="../../addon/edit/continuecomment.js"></script>
<script src="../../addon/comment/comment.js"></script>
<script src="javascript.js"></script>
<link rel="stylesheet" href="../../doc/docs.css">
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
Expand Down Expand Up @@ -68,7 +69,8 @@ <h1>CodeMirror: JavaScript mode</h1>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
matchBrackets: true,
continueComments: "Enter"
continueComments: "Enter",
extraKeys: {"Ctrl-Q": "toggleComment"}
});
</script>

Expand Down
6 changes: 5 additions & 1 deletion mode/javascript/javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}

function maybeoperatorComma(type, value) {
if (type == ",") return cont(expression);
if (type == ",") return pass();
return maybeoperatorNoComma(type, value, maybeoperatorComma);
}
function maybeoperatorNoComma(type, value, me) {
Expand Down Expand Up @@ -453,6 +453,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
},

electricChars: ":{}",
blockCommentStart: jsonMode ? null : "/*",
blockCommentEnd: jsonMode ? null : "*/",
lineComment: jsonMode ? null : "//",

jsonMode: jsonMode
};
Expand All @@ -463,5 +466,6 @@ CodeMirror.defineMIME("text/ecmascript", "javascript");
CodeMirror.defineMIME("application/javascript", "javascript");
CodeMirror.defineMIME("application/ecmascript", "javascript");
CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
8 changes: 0 additions & 8 deletions mode/less/less.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@
CodeMirror.defineMode("less", function(config) {
var indentUnit = config.indentUnit, type;
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$)/;

Expand Down Expand Up @@ -135,8 +129,6 @@ CodeMirror.defineMode("less", function(config) {
//stream.backUp(stream.current().length-1);
//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");
}else if( /\/|[\s\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == "/")) && stream.current().indexOf(".") !== -1){
if(stream.current().substring(stream.current().length-1,stream.current().length) == "{"){
stream.backUp(1);
Expand Down
6 changes: 5 additions & 1 deletion mode/lua/lua.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,11 @@ CodeMirror.defineMode("lua", function(config, parserConfig) {
indent: function(state, textAfter) {
var closing = dedentPartial.test(textAfter);
return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0));
}
},

lineComment: "--",
blockCommentStart: "--[[",
blockCommentEnd: "]]"
};
});

Expand Down
4 changes: 2 additions & 2 deletions mode/markdown/markdown.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {

var htmlFound = CodeMirror.mimeModes.hasOwnProperty("text/html");
var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? "text/html" : "text/plain");
var htmlFound = CodeMirror.modes.hasOwnProperty("xml");
var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain");
var aliases = {
html: "htmlmixed",
js: "javascript",
Expand Down
2 changes: 2 additions & 0 deletions mode/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ CodeMirror.modeInfo = [
{name: 'Asterisk', mime: 'text/x-asterisk', mode: 'asterisk'},
{name: 'C', mime: 'text/x-csrc', mode: 'clike'},
{name: 'C++', mime: 'text/x-c++src', mode: 'clike'},
{name: 'Cobol', mime: 'text/x-cobol', mode: 'cobol'},
{name: 'Java', mime: 'text/x-java', mode: 'clike'},
{name: 'C#', mime: 'text/x-csharp', mode: 'clike'},
{name: 'Scala', mime: 'text/x-scala', mode: 'clike'},
Expand All @@ -26,6 +27,7 @@ CodeMirror.modeInfo = [
{name: 'HTML', mime: 'text/html', mode: 'htmlmixed'},
{name: 'HTTP', mime: 'message/http', mode: 'http'},
{name: 'JavaScript', mime: 'text/javascript', mode: 'javascript'},
{name: 'JSON', mime: 'application/x-json', mode: 'javascript'},
{name: 'JSON', mime: 'application/json', mode: 'javascript'},
{name: 'TypeScript', mime: 'application/typescript', mode: 'javascript'},
{name: 'Jinja2', mime: 'jinja2', mode: 'jinja2'},
Expand Down
5 changes: 4 additions & 1 deletion mode/ocaml/ocaml.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ CodeMirror.defineMode('ocaml', function() {
token: function(stream, state) {
if (stream.eatSpace()) return null;
return state.tokenize(stream, state);
}
},

blockCommentStart: "(*",
blockCommentEnd: "*)"
};
});

Expand Down
3 changes: 3 additions & 0 deletions mode/php/php.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@
},

electricChars: "/{}:",
blockCommentStart: "/*",
blockCommentEnd: "*/",
lineComment: "//",

innerMode: function(state) { return {state: state.curState, mode: state.curMode}; }
};
Expand Down
3 changes: 2 additions & 1 deletion mode/python/python.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,9 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
}

return state.scopes[0].offset;
}
},

lineComment: "#"
};
return external;
});
Expand Down
3 changes: 2 additions & 1 deletion mode/ruby/ruby.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,9 @@ CodeMirror.defineMode("ruby", function(config) {
return ct.indented + (closing ? 0 : config.indentUnit) +
(state.continuedLine ? config.indentUnit : 0);
},
electricChars: "}de" // enD and rescuE

electricChars: "}de", // enD and rescuE
lineComment: "#"
};
});

Expand Down
5 changes: 4 additions & 1 deletion mode/rust/rust.js
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,10 @@ CodeMirror.defineMode("rust", function() {
return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit));
},

electricChars: "{}"
electricChars: "{}",
blockCommentStart: "/*",
blockCommentEnd: "*/",
lineComment: "//"
};
});

Expand Down
35 changes: 8 additions & 27 deletions mode/sass/sass.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,13 @@ CodeMirror.defineMode("sass", function(config) {
return new RegExp("^" + words.join("|"));
};

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"];
var keywords = ["true", "false", "null", "auto"];
var keywordsRegexp = new RegExp("^" + keywords.join("|"));

var operators = ["\\(", "\\)", "=", ">", "<", "==", ">=", "<=", "\\+", "-", "\\!=", "/", "\\*", "%", "and", "or", "not"];
var opRegexp = tokenRegexp(operators);

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


var pseudoElements = [':first-line', ':hover', ':first-letter', ':active', ':visited', ':before', ':after', ':link', ':focus', ':first-child', ':lang'];
var pseudoElementsRegexp = new RegExp("^(" + pseudoElements.join("\\b|") + ")");
var pseudoElementsRegexp = /^::?[\w\-]+/;

var urlTokens = function(stream, state){
var ch = stream.peek();
Expand Down Expand Up @@ -256,25 +245,17 @@ CodeMirror.defineMode("sass", function(config) {
}

// Pseudo element selectors
if (stream.match(pseudoElementsRegexp)){
if (ch == ':' && stream.match(pseudoElementsRegexp)){
return "keyword";
}

// atoms
if (stream.eatWhile(/[\w-&]/)){

var current = stream.current();
// matches a property definition
if (stream.peek() === ":"){
// if this is an html tag and it has a pseudo selector, then it's an atom
if (htmlTag(current) && stream.match(pseudoElementsRegexp, false)){
return "atom";
}else{
stream.next();
return "property";
}
}
return "atom";
if (stream.peek() === ":" && !stream.match(pseudoElementsRegexp, false))
return "property";
else
return "atom";
}

if (stream.match(opRegexp)){
Expand All @@ -298,7 +279,7 @@ CodeMirror.defineMode("sass", function(config) {
dedent(state);
}

if (style === "atom" && htmlTag(current)){
if (style === "atom"){
indent(state);
}

Expand All @@ -312,7 +293,7 @@ CodeMirror.defineMode("sass", function(config) {
var scope = state.scopes[i];

if (scope.offset <= withCurrentIndent){
newScopes.push(scope);
newScopes.push(scope);
}
}

Expand Down
4 changes: 3 additions & 1 deletion mode/scheme/scheme.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ CodeMirror.defineMode("scheme", function () {
indent: function (state) {
if (state.indentStack == null) return state.indentation;
return state.indentStack.indent;
}
},

lineComment: ";;"
};
});

Expand Down
10 changes: 6 additions & 4 deletions mode/smalltalk/smalltalk.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CodeMirror.defineMode('smalltalk', function(config) {

var specialChars = /[+\-\/\\*~<>=@%|&?!.:;^]/;
var specialChars = /[+\-\/\\*~<>=@%|&?!.,:;^]/;
var keywords = /true|false|nil|self|super|thisContext/;

var Context = function(tokenizer, parent) {
Expand Down Expand Up @@ -36,11 +36,14 @@ CodeMirror.defineMode('smalltalk', function(config) {
token = nextString(stream, new Context(nextString, context));

} else if (aChar === '#') {
stream.eatWhile(/[^ .]/);
stream.eatWhile(/[^ .\[\]()]/);
token.name = 'string-2';

} else if (aChar === '$') {
stream.eatWhile(/[^ ]/);
if (stream.next() === '<') {
stream.eatWhile(/[^ >]/);
stream.next();
}
token.name = 'string-2';

} else if (aChar === '|' && state.expectVariable) {
Expand Down Expand Up @@ -118,7 +121,6 @@ CodeMirror.defineMode('smalltalk', function(config) {
state.context = token.context;
state.expectVariable = token.eos;

state.lastToken = token;
return token.name;
},

Expand Down
1 change: 0 additions & 1 deletion mode/sql/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<link rel="stylesheet" href="../../lib/codemirror.css" />
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/codemirror.js"></script>
<script src="../../lib/util/continuelist.js"></script>
<script src="sql.js"></script>
<style>
.CodeMirror {
Expand Down
7 changes: 3 additions & 4 deletions mode/sql/sql.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {
return state.tokenize(stream, state);
} else if (ch == ".") {
// .1 for 0.1
if (stream.match(/^[0-9eE]+/) && support.zerolessFloat == true) {
if (support.zerolessFloat == true && stream.match(/^(?:\d+(?:e\d*)?|\d*e\d+)/i)) {
return "number";
}
// .table_name (ODBC)
Expand Down Expand Up @@ -166,10 +166,9 @@ CodeMirror.defineMode("sql", function(config, parserConfig) {

// `identifier`
function hookIdentifier(stream) {
var escaped = false, ch;
var ch;
while ((ch = stream.next()) != null) {
if (ch == "`" && !escaped) return "variable-2";
escaped = !escaped && ch == "`";
if (ch == "`" && !stream.eat("`")) return "variable-2";
}
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion mode/stex/stex.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ CodeMirror.defineMode("stex", function() {
}

// white space control characters
if (source.match(/^\\[,;!\/]/)) {
if (source.match(/^\\[,;!\/\\]/)) {
return "tag";
}

Expand Down
3 changes: 3 additions & 0 deletions mode/stex/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,7 @@
MT("mathWithComment",
"[keyword $][variable-2 x] [comment % $]",
"[variable-2 y][keyword $] other text");

MT("lineBreakArgument",
"[tag \\\\][bracket [[][atom 1cm][bracket ]]]");
})();
2 changes: 2 additions & 0 deletions mode/xml/xml.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
},

electricChars: "/",
blockCommentStart: "<!--",
blockCommentEnd: "-->",

configuration: parserConfig.htmlMode ? "html" : "xml"
};
Expand Down
4 changes: 3 additions & 1 deletion mode/yaml/yaml.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ CodeMirror.defineMode("yaml", function() {
var esc = state.escaped;
state.escaped = false;
/* comments */
if (ch == "#") { stream.skipToEnd(); return "comment"; }
if (ch == "#" && (stream.pos == 0 || /\s/.test(stream.string.charAt(stream.pos - 1)))) {
stream.skipToEnd(); return "comment";
}
if (state.literal && stream.indentation() > state.keyCol) {
stream.skipToEnd(); return "string";
} else if (state.literal) { state.literal = false; }
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":"3.12.00",
"version":"3.13.00",
"main": "lib/codemirror.js",
"description": "In-browser code editing made bearable",
"licenses": [{"type": "MIT",
Expand Down
46 changes: 46 additions & 0 deletions test/comment_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
namespace = "comment_";

(function() {
function test(name, mode, run, before, after) {
return testCM(name, function(cm) {
run(cm);
eq(cm.getValue(), after);
}, {value: before, mode: mode});
}

var simpleProg = "function foo() {\n return bar;\n}";

test("block", "javascript", function(cm) {
cm.blockComment(Pos(0, 3), Pos(3, 0), {blockCommentLead: " *"});
}, simpleProg + "\n", "/* function foo() {\n * return bar;\n * }\n */");

test("blockToggle", "javascript", function(cm) {
cm.blockComment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"});
cm.uncomment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"});
}, simpleProg, simpleProg);

test("line", "javascript", function(cm) {
cm.lineComment(Pos(1, 1), Pos(1, 1));
}, simpleProg, "function foo() {\n// return bar;\n}");

test("lineToggle", "javascript", function(cm) {
cm.lineComment(Pos(0, 0), Pos(2, 1));
cm.uncomment(Pos(0, 0), Pos(2, 1));
}, simpleProg, simpleProg);

test("fallbackToBlock", "css", function(cm) {
cm.lineComment(Pos(0, 0), Pos(2, 1));
}, "html {\n border: none;\n}", "/* html {\n border: none;\n} */");

test("fallbackToLine", "ruby", function(cm) {
cm.blockComment(Pos(0, 0), Pos(1));
}, "def blah()\n return hah\n", "# def blah()\n# return hah\n");

test("commentRange", "javascript", function(cm) {
cm.blockComment(Pos(1, 2), Pos(1, 13), {fullLines: false});
}, simpleProg, "function foo() {\n /*return bar;*/\n}");

test("indented", "javascript", function(cm) {
cm.lineComment(Pos(1, 0), Pos(2), {indent: true});
}, simpleProg, "function foo() {\n // return bar;\n // }");
})();
3 changes: 2 additions & 1 deletion test/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ function test(name, run, expectedFail) {
tests.push({name: name, func: run, expectedFail: expectedFail});
return name;
}
var namespace = "";
function testCM(name, run, opts, expectedFail) {
return test("core_" + name, function() {
return test(namespace + name, function() {
var place = document.getElementById("testground"), cm = CodeMirror(place, opts);
var successful = false;
try {
Expand Down
12 changes: 10 additions & 2 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<script src="../lib/codemirror.js"></script>
<script src="../addon/mode/overlay.js"></script>
<script src="../addon/search/searchcursor.js"></script>
<script src="../addon/dialog/dialog.js"></script>
<script src="../addon/comment/comment.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../keymap/vim.js"></script>
Expand Down Expand Up @@ -53,10 +55,16 @@ <h1>CodeMirror: Test Suite</h1>
<script src="driver.js"></script>
<script src="test.js"></script>
<script src="doc_test.js"></script>
<script src="comment_test.js"></script>
<script src="mode_test.js"></script>
<script src="../mode/css/css.js"></script>
<script src="../mode/css/test.js"></script>
<script src="../mode/css/scss_test.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../mode/htmlmixed/htmlmixed.js"></script>
<script src="../mode/ruby/ruby.js"></script>
<script src="../mode/haml/haml.js"></script>
<script src="../mode/haml/test.js"></script>
<script src="../mode/markdown/markdown.js"></script>
<script src="../mode/markdown/test.js"></script>
<script src="../mode/gfm/gfm.js"></script>
Expand Down Expand Up @@ -84,7 +92,7 @@ <h1>CodeMirror: Test Suite</h1>
running = false, // Flag that states tests are running
quit = false, // Flag to quit tests ASAP
verbose = false; // Adds message for *every* test to output

function runHarness(){
if (running) {
quit = true;
Expand Down Expand Up @@ -115,7 +123,7 @@ <h1>CodeMirror: Test Suite</h1>
"</form>";
runTests(displayTest);
}

function setStatus(message, className, force){
if (quit && !force) return;
if (!message) throw("must provide message");
Expand Down
5 changes: 4 additions & 1 deletion test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/);
if (opera_version) opera_version = Number(opera_version);
var opera_lt10 = opera && (!opera_version || opera_version < 10);

namespace = "core_";

test("core_fromTextArea", function() {
var te = document.getElementById("code");
te.value = "CONTENT";
Expand Down Expand Up @@ -1013,7 +1015,8 @@ testCM("verticalMovementCommandsWrapping", function(cm) {

testCM("rtlMovement", function(cm) {
forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج",
"خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر"], function(line) {
"خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر",
"<img src=\"/בדיקה3.jpg\">"], function(line) {
var inv = line.charAt(0) == "خ";
cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart");
var cursor = byClassName(cm.getWrapperElement(), "CodeMirror-cursor")[0];
Expand Down
Loading