Move to latest codemirror (3.02)

dev/git-series/gccdum
Matt Godbolt 10 years ago
parent 3075f966d1
commit 091bf37762

@ -7,3 +7,9 @@ Notes:
* storage in both hash tag and in local storage need to change. Specifically they are too tied to the notion of a single compiler.
* should ensure backwards compatibility: store off some hash tags and test the decode to the same view in the new scheme.
NB
--
Killing due to time seems broken.

@ -1,6 +1,7 @@
# Default settings for GCC Explorer.
port=10240
compileTimeoutMs=4000
compilers=/usr/bin/gdc:/usr/bin/gdc-4.4:/usr/bin/gdc-4.6
compileFilename=example.d
postProcess=d/demangle
compilers=/usr/bin/g++-4.4:/usr/bin/g++-4.5:/usr/bin/g++-4.6:/usr/bin/g++-4.7:/usr/bin/clang++:/home/mgodbolt/apps/intel-icc-oss/bin/icc:/site/apps/gcc-4.7.2-drw.patched.6/bin/g++
#compilers=/usr/bin/gdc:/usr/bin/gdc-4.4:/usr/bin/gdc-4.6
#compileFilename=example.d
#postProcess=d/demangle

@ -39,7 +39,7 @@ function parseLines(lines, callback) {
function clearBackground(cm) {
for (var i = 0; i < cm.lineCount(); ++i) {
cm.setLineClass(i, null, null);
cm.removeLineClass(i, "background", null);
}
}
@ -57,11 +57,12 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback) {
cppEditor = CodeMirror.fromTextArea(domRoot.find(".editor textarea")[0], {
lineNumbers: true,
matchBrackets: true,
useCPP: true,
mode: "text/x-c++src",
onChange: onChange
gutters: ["CodeMirror-linenumbers", "info-margin"],
matchBrackets: true,
useCPP: true,
mode: "text/x-c++src"
});
cppEditor.on("change", onChange);
asmCodeMirror = CodeMirror.fromTextArea(domRoot.find(".asm textarea")[0], {
lineNumbers: true,
matchBrackets: true,
@ -85,6 +86,10 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback) {
domRoot.find('.compiler_options').val(getSetting('compilerOptions'));
}
function makeErrNode(tooltip) {
return $('<div></div>').text(">").addClass("error").attr("title", tooltip)[0];
}
function onCompileResponse(data) {
var stdout = data.stdout || "";
var stderr = data.stderr || "";
@ -95,11 +100,11 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback) {
}
$('.result .output :visible').remove();
var highlightLine = (data.asm == null);
for (var i = 0; i < cppEditor.lineCount(); ++i) cppEditor.setMarker(i);
for (var i = 0; i < cppEditor.lineCount(); ++i) cppEditor.setGutterMarker(i, "info-margin", null);
parseLines(stderr + stdout, function(lineNum, msg) {
var elem = $('.result .output .template').clone().appendTo('.result .output').removeClass('template');
if (lineNum) {
cppEditor.setMarker(lineNum - 1, null, "error");
cppEditor.setGutterMarker(lineNum - 1, "info-margin", makeErrNode(msg));
elem.html($('<a href="#">').append(lineNum + " : " + msg)).click(function() {
cppEditor.setSelection({line: lineNum - 1, ch: 0}, {line: lineNum, ch: 0});
return false;
@ -141,10 +146,10 @@ function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback) {
clearBackground(asmCodeMirror);
if (filters.colouriseAsm) {
$.each(numberedLines.source, function(line, ordinal) {
cppEditor.setLineClass(parseInt(line), null, "rainbow-" + (ordinal % NumRainbowColours));
cppEditor.addLineClass(parseInt(line), "background", "rainbow-" + (ordinal % NumRainbowColours));
});
$.each(numberedLines.asm, function(line, ordinal) {
asmCodeMirror.setLineClass(parseInt(line), null, "rainbow-" + (ordinal % NumRainbowColours));
asmCodeMirror.addLineClass(parseInt(line), "background", "rainbow-" + (ordinal % NumRainbowColours));
});
}
}

@ -1,18 +1,23 @@
.CodeMirror-dialog {
position: relative;
}
.CodeMirror-dialog > div {
position: absolute;
top: 0; left: 0; right: 0;
left: 0; right: 0;
background: white;
border-bottom: 1px solid #eee;
z-index: 15;
padding: .1em .8em;
overflow: hidden;
color: #333;
}
.CodeMirror-dialog-top {
border-bottom: 1px solid #eee;
top: 0;
}
.CodeMirror-dialog-bottom {
border-top: 1px solid #eee;
bottom: 0;
}
.CodeMirror-dialog input {
border: none;
outline: none;
@ -24,4 +29,4 @@
.CodeMirror-dialog button {
font-size: 70%;
}
}

@ -1,16 +1,21 @@
// Open simple dialogs on top of an editor. Relies on dialog.css.
(function() {
function dialogDiv(cm, template) {
function dialogDiv(cm, template, bottom) {
var wrap = cm.getWrapperElement();
var dialog = wrap.insertBefore(document.createElement("div"), wrap.firstChild);
dialog.className = "CodeMirror-dialog";
dialog.innerHTML = '<div>' + template + '</div>';
var dialog;
dialog = wrap.appendChild(document.createElement("div"));
if (bottom) {
dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
} else {
dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
}
dialog.innerHTML = template;
return dialog;
}
CodeMirror.defineExtension("openDialog", function(template, callback) {
var dialog = dialogDiv(this, template);
CodeMirror.defineExtension("openDialog", function(template, callback, options) {
var dialog = dialogDiv(this, template, options && options.bottom);
var closed = false, me = this;
function close() {
if (closed) return;
@ -19,7 +24,7 @@
}
var inp = dialog.getElementsByTagName("input")[0], button;
if (inp) {
CodeMirror.connect(inp, "keydown", function(e) {
CodeMirror.on(inp, "keydown", function(e) {
if (e.keyCode == 13 || e.keyCode == 27) {
CodeMirror.e_stop(e);
close();
@ -27,21 +32,22 @@
if (e.keyCode == 13) callback(inp.value);
}
});
if (options && options.value) inp.value = options.value;
inp.focus();
CodeMirror.connect(inp, "blur", close);
CodeMirror.on(inp, "blur", close);
} else if (button = dialog.getElementsByTagName("button")[0]) {
CodeMirror.connect(button, "click", function() {
CodeMirror.on(button, "click", function() {
close();
me.focus();
});
button.focus();
CodeMirror.connect(button, "blur", close);
CodeMirror.on(button, "blur", close);
}
return close;
});
CodeMirror.defineExtension("openConfirm", function(template, callbacks) {
var dialog = dialogDiv(this, template);
CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
var dialog = dialogDiv(this, template, options && options.bottom);
var buttons = dialog.getElementsByTagName("button");
var closed = false, me = this, blurring = 1;
function close() {
@ -54,17 +60,17 @@
for (var i = 0; i < buttons.length; ++i) {
var b = buttons[i];
(function(callback) {
CodeMirror.connect(b, "click", function(e) {
CodeMirror.on(b, "click", function(e) {
CodeMirror.e_preventDefault(e);
close();
if (callback) callback(me);
});
})(callbacks[i]);
CodeMirror.connect(b, "blur", function() {
CodeMirror.on(b, "blur", function() {
--blurring;
setTimeout(function() { if (blurring <= 0) close(); }, 200);
});
CodeMirror.connect(b, "focus", function() { ++blurring; });
CodeMirror.on(b, "focus", function() { ++blurring; });
}
});
})();
})();

@ -0,0 +1,85 @@
/**
* Tag-closer extension for CodeMirror.
*
* This extension adds an "autoCloseTags" option that can be set to
* either true to get the default behavior, or an object to further
* configure its behavior.
*
* These are supported options:
*
* `whenClosing` (default true)
* Whether to autoclose when the '/' of a closing tag is typed.
* `whenOpening` (default true)
* Whether to autoclose the tag when the final '>' of an opening
* tag is typed.
* `dontCloseTags` (default is empty tags for HTML, none for XML)
* An array of tag names that should not be autoclosed.
* `indentTags` (default is block tags for HTML, none for XML)
* An array of tag names that should, when opened, cause a
* blank line to be added inside the tag, and the blank line and
* closing line to be indented.
*
* See demos/closetag.html for a usage example.
*/
(function() {
CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
if (val && (old == CodeMirror.Init || !old)) {
var map = {name: "autoCloseTags"};
if (typeof val != "object" || val.whenClosing)
map["'/'"] = function(cm) { autoCloseTag(cm, '/'); };
if (typeof val != "object" || val.whenOpening)
map["'>'"] = function(cm) { autoCloseTag(cm, '>'); };
cm.addKeyMap(map);
} else if (!val && (old != CodeMirror.Init && old)) {
cm.removeKeyMap("autoCloseTags");
}
});
var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
"source", "track", "wbr"];
var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
"h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
function autoCloseTag(cm, ch) {
var pos = cm.getCursor(), tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
if (inner.mode.name != "xml") throw CodeMirror.Pass;
var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
if (ch == ">" && state.tagName) {
var tagName = state.tagName;
if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
var lowerTagName = tagName.toLowerCase();
// Don't process the '>' at the end of an end-tag or self-closing tag
if (tok.type == "tag" && state.type == "closeTag" ||
/\/\s*$/.test(tok.string) ||
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1)
throw CodeMirror.Pass;
var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1;
cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "</" + tagName + ">",
doIndent ? {line: pos.line + 1, ch: 0} : {line: pos.line, ch: pos.ch + 1});
if (doIndent) {
cm.indentLine(pos.line + 1);
cm.indentLine(pos.line + 2);
}
return;
} else if (ch == "/" && tok.type == "tag" && tok.string == "<") {
var tagName = state.context && state.context.tagName;
if (tagName) cm.replaceSelection("/" + tagName + ">", "end");
return;
}
throw CodeMirror.Pass;
}
function indexOf(collection, elt) {
if (collection.indexOf) return collection.indexOf(elt);
for (var i = 0, e = collection.length; i < e; ++i)
if (collection[i] == elt) return i;
return -1;
}
})();

@ -0,0 +1,36 @@
(function() {
var modes = ["clike", "css", "javascript"];
for (var i = 0; i < modes.length; ++i)
CodeMirror.extendMode(modes[i], {blockCommentStart: "/*",
blockCommentEnd: "*/",
blockCommentContinue: " * "});
CodeMirror.commands.newlineAndIndentContinueComment = function(cm) {
var pos = cm.getCursor(), token = cm.getTokenAt(pos);
var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode;
var space;
if (token.type == "comment" && mode.blockCommentStart) {
var end = token.string.indexOf(mode.blockCommentEnd);
var full = cm.getRange({line: pos.line, ch: 0}, {line: pos.line, ch: token.end}), found;
if (end != -1 && end == token.string.length - mode.blockCommentEnd.length) {
// Comment ended, don't continue it
} else if (token.string.indexOf(mode.blockCommentStart) == 0) {
space = full.slice(0, token.start);
if (!/^\s*$/.test(space)) {
space = "";
for (var i = 0; i < token.start; ++i) space += " ";
}
} else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
found + mode.blockCommentContinue.length > token.start &&
/^\s*$/.test(full.slice(0, found))) {
space = full.slice(0, found);
}
}
if (space != null)
cm.replaceSelection("\n" + space + mode.blockCommentContinue, "end");
else
cm.execCommand("newlineAndIndent");
};
})();

@ -0,0 +1,28 @@
(function() {
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
var pos = cm.getCursor(), token = cm.getTokenAt(pos);
var space;
if (token.className == "string") {
var full = cm.getRange({line: pos.line, ch: 0}, {line: pos.line, ch: token.end});
var listStart = /\*|\d+\./, listContinue;
if (token.string.search(listStart) == 0) {
var reg = /^[\W]*(\d+)\./g;
var matches = reg.exec(full);
if(matches)
listContinue = (parseInt(matches[1]) + 1) + ". ";
else
listContinue = "* ";
space = full.slice(0, token.start);
if (!/^\s*$/.test(space)) {
space = "";
for (var i = 0; i < token.start; ++i) space += " ";
}
}
}
if (space != null)
cm.replaceSelection("\n" + space + listContinue, "end");
else
cm.execCommand("newlineAndIndent");
};
})();

@ -0,0 +1,63 @@
(function() {
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
function findMatchingBracket(cm) {
var cur = cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
if (!match) return null;
var forward = match.charAt(1) == ">", d = forward ? 1 : -1;
var style = cm.getTokenAt({line: cur.line, ch: pos + 1}).type;
var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
function scan(line, lineNo, start) {
if (!line.text) return;
var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1;
if (start != null) pos = start + d;
for (; pos != end; pos += d) {
var ch = line.text.charAt(pos);
if (re.test(ch) && cm.getTokenAt({line: lineNo, ch: pos + 1}).type == style) {
var match = matching[ch];
if (match.charAt(1) == ">" == forward) stack.push(ch);
else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
else if (!stack.length) return {pos: pos, match: true};
}
}
}
for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) {
if (i == cur.line) found = scan(line, i, pos);
else found = scan(cm.getLineHandle(i), i);
if (found) break;
}
return {from: {line: cur.line, ch: pos}, to: found && {line: i, ch: found.pos}, match: found && found.match};
}
function matchBrackets(cm, autoclear) {
var found = findMatchingBracket(cm);
if (!found) return;
var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
var one = cm.markText(found.from, {line: found.from.line, ch: found.from.ch + 1},
{className: style});
var two = found.to && cm.markText(found.to, {line: found.to.line, ch: found.to.ch + 1},
{className: style});
var clear = function() {
cm.operation(function() { one.clear(); two && two.clear(); });
};
if (autoclear) setTimeout(clear, 800);
else return clear;
}
var currentlyHighlighted = null;
function doMatchBrackets(cm) {
cm.operation(function() {
if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false);
});
}
CodeMirror.defineOption("matchBrackets", false, function(cm, val) {
if (val) cm.on("cursorActivity", doMatchBrackets);
else cm.off("cursorActivity", doMatchBrackets);
});
CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
CodeMirror.defineExtension("findMatchingBracket", function(){return findMatchingBracket(this);});
})();

@ -0,0 +1,68 @@
(function() {
CodeMirror.defineOption("collapseRange", false, function(cm, val, old) {
var wasOn = old && old != CodeMirror.Init;
if (val && !wasOn)
enableRangeCollapsing(cm);
else if (!val && wasOn)
disableRangeCollapsing(cm);
});
var gutterClass = "CodeMirror-collapserange";
function enableRangeCollapsing(cm) {
cm.on("gutterClick", gutterClick);
cm.setOption("gutters", (cm.getOption("gutters") || []).concat([gutterClass]));
}
function disableRangeCollapsing(cm) {
cm.rangeCollapseStart = null;
cm.off("gutterClick", gutterClick);
var gutters = cm.getOption("gutters");
for (var i = 0; i < gutters.length && gutters[i] != gutterClass; ++i) {}
cm.setOption("gutters", gutters.slice(0, i).concat(gutters.slice(i + 1)));
}
function gutterClick(cm, line, gutter) {
if (gutter != gutterClass) return;
var start = cm.rangeCollapseStart;
if (start) {
var old = cm.getLineNumber(start);
cm.setGutterMarker(start, gutterClass, null);
cm.rangeCollapseStart = null;
var from = Math.min(old, line), to = Math.max(old, line);
if (from != to) {
// Finish this fold
var fold = cm.markText({line: from + 1, ch: 0}, {line: to - 1}, {
collapsed: true,
inclusiveLeft: true,
inclusiveRight: true,
clearOnEnter: true
});
var clear = function() {
cm.setGutterMarker(topLine, gutterClass, null);
cm.setGutterMarker(botLine, gutterClass, null);
fold.clear();
};
var topLine = cm.setGutterMarker(from, gutterClass, makeMarker(true, true, clear));
var botLine = cm.setGutterMarker(to, gutterClass, makeMarker(false, true, clear));
CodeMirror.on(fold, "clear", clear);
return;
}
}
// Start a new fold
cm.rangeCollapseStart = cm.setGutterMarker(line, gutterClass, makeMarker(true, false));
}
function makeMarker(isTop, isFinished, handler) {
var node = document.createElement("div");
node.innerHTML = isTop ? "\u25bc" : "\u25b2";
if (!isFinished) node.style.color = "red";
node.style.fontSize = "85%";
node.style.cursor = "pointer";
if (handler) CodeMirror.on(node, "mousedown", handler);
return node;
}
})();

@ -1,15 +1,15 @@
// the tagRangeFinder function is
// Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
// released under the MIT license (../../LICENSE) like the rest of CodeMirror
CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
CodeMirror.tagRangeFinder = function(cm, start) {
var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");
var lineText = cm.getLine(line);
var lineText = cm.getLine(start.line);
var found = false;
var tag = null;
var pos = 0;
var pos = start.ch;
while (!found) {
pos = lineText.indexOf("<", pos);
if (-1 == pos) // no tag on line
@ -18,28 +18,26 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
pos++;
continue;
}
// ok we weem to have a start tag
// ok we seem to have a start tag
if (!lineText.substr(pos + 1).match(xmlNAMERegExp)) { // not a tag name...
pos++;
continue;
}
var gtPos = lineText.indexOf(">", pos + 1);
if (-1 == gtPos) { // end of start tag not in line
var l = line + 1;
var l = start.line + 1;
var foundGt = false;
var lastLine = cm.lineCount();
while (l < lastLine && !foundGt) {
var lt = cm.getLine(l);
var gt = lt.indexOf(">");
if (-1 != gt) { // found a >
gtPos = lt.indexOf(">");
if (-1 != gtPos) { // found a >
foundGt = true;
var slash = lt.lastIndexOf("/", gt);
if (-1 != slash && slash < gt) {
var str = lineText.substr(slash, gt - slash + 1);
if (!str.match( /\/\s*\>/ )) { // yep, that's the end of empty tag
if (hideEnd === true) l++;
return l;
}
var slash = lt.lastIndexOf("/", gtPos);
if (-1 != slash && slash < gtPos) {
var str = lineText.substr(slash, gtPos - slash + 1);
if (!str.match( /\/\s*\>/ )) // yep, that's the end of empty tag
return;
}
}
l++;
@ -83,10 +81,10 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
if (found) {
var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\\s)|(\\<" + tag + "$)";
var startTagRegExp = new RegExp(startTag, "g");
var startTagRegExp = new RegExp(startTag);
var endTag = "</" + tag + ">";
var depth = 1;
var l = line + 1;
var l = start.line + 1;
var lastLine = cm.lineCount();
while (l < lastLine) {
lineText = cm.getLine(l);
@ -97,10 +95,8 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
depth--;
else
depth++;
if (!depth) {
if (hideEnd === true) l++;
return l;
}
if (!depth) return {from: {line: start.line, ch: gtPos + 1},
to: {line: l, ch: match.index}};
}
}
l++;
@ -109,17 +105,18 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
}
};
CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
var lineText = cm.getLine(line), at = lineText.length, startChar, tokenType;
CodeMirror.braceRangeFinder = function(cm, start) {
var line = start.line, lineText = cm.getLine(line);
var at = lineText.length, startChar, tokenType;
for (;;) {
var found = lineText.lastIndexOf("{", at);
if (found < 0) break;
tokenType = cm.getTokenAt({line: line, ch: found}).className;
if (found < start.ch) break;
tokenType = cm.getTokenAt({line: line, ch: found}).type;
if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
at = found - 1;
}
if (startChar == null || lineText.lastIndexOf("}") > startChar) return;
var count = 1, lastLine = cm.lineCount(), end;
var count = 1, lastLine = cm.lineCount(), end, endCh;
outer: for (var i = line + 1; i < lastLine; ++i) {
var text = cm.getLine(i), pos = 0;
for (;;) {
@ -128,69 +125,59 @@ CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
if (nextClose < 0) nextClose = text.length;
pos = Math.min(nextOpen, nextClose);
if (pos == text.length) break;
if (cm.getTokenAt({line: i, ch: pos + 1}).className == tokenType) {
if (cm.getTokenAt({line: i, ch: pos + 1}).type == tokenType) {
if (pos == nextOpen) ++count;
else if (!--count) { end = i; break outer; }
else if (!--count) { end = i; endCh = pos; break outer; }
}
++pos;
}
}
if (end == null || end == line + 1) return;
if (hideEnd === true) end++;
return end;
return {from: {line: line, ch: startChar + 1},
to: {line: end, ch: endCh}};
};
CodeMirror.indentRangeFinder = function(cm, line) {
var tabSize = cm.getOption("tabSize");
var myIndent = cm.getLineHandle(line).indentation(tabSize), last;
for (var i = line + 1, end = cm.lineCount(); i < end; ++i) {
var handle = cm.getLineHandle(i);
if (!/^\s*$/.test(handle.text)) {
if (handle.indentation(tabSize) <= myIndent) break;
last = i;
}
CodeMirror.indentRangeFinder = function(cm, start) {
var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);
var myIndent = CodeMirror.countColumn(firstLine, null, tabSize);
for (var i = start.line + 1, end = cm.lineCount(); i < end; ++i) {
var curLine = cm.getLine(i);
if (CodeMirror.countColumn(curLine, null, tabSize) < myIndent &&
CodeMirror.countColumn(cm.getLine(i-1), null, tabSize) > myIndent)
return {from: {line: start.line, ch: firstLine.length},
to: {line: i, ch: curLine.length}};
}
if (!last) return null;
return last + 1;
};
CodeMirror.newFoldFunction = function(rangeFinder, markText, hideEnd) {
var folded = [];
if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">&#x25bc;</div>%N%';
function isFolded(cm, n) {
for (var i = 0; i < folded.length; ++i) {
var start = cm.lineInfo(folded[i].start);
if (!start) folded.splice(i--, 1);
else if (start.line == n) return {pos: i, region: folded[i]};
}
CodeMirror.newFoldFunction = function(rangeFinder, widget) {
if (widget == null) widget = "\u2194";
if (typeof widget == "string") {
var text = document.createTextNode(widget);
widget = document.createElement("span");
widget.appendChild(text);
widget.className = "CodeMirror-foldmarker";
}
function expand(cm, region) {
cm.clearMarker(region.start);
for (var i = 0; i < region.hidden.length; ++i)
cm.showLine(region.hidden[i]);
}
return function(cm, pos) {
if (typeof pos == "number") pos = {line: pos, ch: 0};
var range = rangeFinder(cm, pos);
if (!range) return;
return function(cm, line) {
cm.operation(function() {
var known = isFolded(cm, line);
if (known) {
folded.splice(known.pos, 1);
expand(cm, known.region);
} else {
var end = rangeFinder(cm, line, hideEnd);
if (end == null) return;
var hidden = [];
for (var i = line + 1; i < end; ++i) {
var handle = cm.hideLine(i);
if (handle) hidden.push(handle);
}
var first = cm.setMarker(line, markText);
var region = {start: first, hidden: hidden};
cm.onDeleteLine(first, function() { expand(cm, region); });
folded.push(region);
var present = cm.findMarksAt(range.from), cleared = 0;
for (var i = 0; i < present.length; ++i) {
if (present[i].__isFold) {
++cleared;
present[i].clear();
}
}
if (cleared) return;
var myWidget = widget.cloneNode(true);
CodeMirror.on(myWidget, "mousedown", function() {myRange.clear();});
var myRange = cm.markText(range.from, range.to, {
replacedWith: myWidget,
clearOnEnter: true,
__isFold: true
});
};
};

@ -0,0 +1,114 @@
(function() {
CodeMirror.extendMode("css", {
commentStart: "/*",
commentEnd: "*/",
newlineAfterToken: function(_type, content) {
return /^[;{}]$/.test(content);
}
});
CodeMirror.extendMode("javascript", {
commentStart: "/*",
commentEnd: "*/",
// FIXME semicolons inside of for
newlineAfterToken: function(_type, content, textAfter, state) {
if (this.jsonMode) {
return /^[\[,{]$/.test(content) || /^}/.test(textAfter);
} else {
if (content == ";" && state.lexical && state.lexical.type == ")") return false;
return /^[;{}]$/.test(content) && !/^;/.test(textAfter);
}
}
});
var inlineElements = /^(a|abbr|acronym|area|base|bdo|big|br|button|caption|cite|code|col|colgroup|dd|del|dfn|em|frame|hr|iframe|img|input|ins|kbd|label|legend|link|map|object|optgroup|option|param|q|samp|script|select|small|span|strong|sub|sup|textarea|tt|var)$/;
CodeMirror.extendMode("xml", {
commentStart: "<!--",
commentEnd: "-->",
newlineAfterToken: function(type, content, textAfter, state) {
var inline = false;
if (this.configuration == "html")
inline = state.context ? inlineElements.test(state.context.tagName) : false;
return !inline && ((type == "tag" && />$/.test(content) && state.context) ||
/^</.test(textAfter));
}
});
// Comment/uncomment the specified range
CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
var cm = this, curMode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(from).state).mode;
cm.operation(function() {
if (isComment) { // Comment range
cm.replaceRange(curMode.commentEnd, to);
cm.replaceRange(curMode.commentStart, from);
if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
cm.setCursor(from.line, from.ch + curMode.commentStart.length);
} else { // Uncomment range
var selText = cm.getRange(from, to);
var startIndex = selText.indexOf(curMode.commentStart);
var endIndex = selText.lastIndexOf(curMode.commentEnd);
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
// Take string till comment start
selText = selText.substr(0, startIndex)
// From comment start till comment end
+ selText.substring(startIndex + curMode.commentStart.length, endIndex)
// From comment end till string end
+ selText.substr(endIndex + curMode.commentEnd.length);
}
cm.replaceRange(selText, from, to);
}
});
});
// Applies automatic mode-aware indentation to the specified range
CodeMirror.defineExtension("autoIndentRange", function (from, to) {
var cmInstance = this;
this.operation(function () {
for (var i = from.line; i <= to.line; i++) {
cmInstance.indentLine(i, "smart");
}
});
});
// Applies automatic formatting to the specified range
CodeMirror.defineExtension("autoFormatRange", function (from, to) {
var cm = this;
var outer = cm.getMode(), text = cm.getRange(from, to).split("\n");
var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state);
var tabSize = cm.getOption("tabSize");
var out = "", lines = 0, atSol = from.ch == 0;
function newline() {
out += "\n";
atSol = true;
++lines;
}
for (var i = 0; i < text.length; ++i) {
var stream = new CodeMirror.StringStream(text[i], tabSize);
while (!stream.eol()) {
var inner = CodeMirror.innerMode(outer, state);
var style = outer.token(stream, state), cur = stream.current();
stream.start = stream.pos;
if (!atSol || /\S/.test(cur)) {
out += cur;
atSol = false;
}
if (!atSol && inner.mode.newlineAfterToken &&
inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i+1] || "", inner.state))
newline();
}
if (!stream.pos && outer.blankLine) outer.blankLine(state);
if (!atSol && i < text.length - 1) newline();
}
cm.operation(function () {
cm.replaceRange(out, from, to);
for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur)
cm.indentLine(cur, "smart");
cm.setSelection(from, cm.getCursor(false));
});
});
})();

@ -16,16 +16,16 @@
return arr.indexOf(item) != -1;
}
function scriptHint(editor, keywords, getToken) {
function scriptHint(editor, keywords, getToken, options) {
// Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
// If it's not a 'word-style' token, ignore the token.
if (!/^[\w$_]*$/.test(token.string)) {
token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
className: token.string == "." ? "property" : null};
type: token.string == "." ? "property" : null};
}
// If it is a property, find out what it is a property of.
while (tprop.className == "property") {
while (tprop.type == "property") {
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
if (tprop.string != ".") return;
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
@ -40,21 +40,22 @@
}
} while (level > 0);
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
if (tprop.className == 'variable')
tprop.className = 'function';
else return; // no clue
if (tprop.type.indexOf("variable") === 0)
tprop.type = "function";
else return; // no clue
}
if (!context) var context = [];
context.push(tprop);
}
return {list: getCompletions(token, context, keywords),
return {list: getCompletions(token, context, keywords, options),
from: {line: cur.line, ch: token.start},
to: {line: cur.line, ch: token.end}};
}
CodeMirror.javascriptHint = function(editor) {
CodeMirror.javascriptHint = function(editor, options) {
return scriptHint(editor, javascriptKeywords,
function (e, cur) {return e.getTokenAt(cur);});
function (e, cur) {return e.getTokenAt(cur);},
options);
};
function getCoffeeScriptToken(editor, cur) {
@ -65,18 +66,18 @@
if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
token.end = token.start;
token.string = '.';
token.className = "property";
token.type = "property";
}
else if (/^\.[\w$_]*$/.test(token.string)) {
token.className = "property";
token.type = "property";
token.start++;
token.string = token.string.replace(/\./, '');
}
return token;
}
CodeMirror.coffeescriptHint = function(editor) {
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken);
CodeMirror.coffeescriptHint = function(editor, options) {
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
};
var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
@ -89,7 +90,7 @@
var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
function getCompletions(token, context, keywords) {
function getCompletions(token, context, keywords, options) {
var found = [], start = token.string;
function maybeAdd(str) {
if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
@ -105,13 +106,15 @@
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.className == "variable")
base = window[obj.string];
else if (obj.className == "string")
if (obj.type.indexOf("variable") === 0) {
if (options && options.additionalContext)
base = options.additionalContext[obj.string];
base = base || window[obj.string];
} else if (obj.type == "string") {
base = "";
else if (obj.className == "atom")
} else if (obj.type == "atom") {
base = 1;
else if (obj.className == "function") {
} else if (obj.type == "function") {
if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
(typeof window.jQuery == 'function'))
base = window.jQuery();
@ -124,8 +127,9 @@
}
else {
// If not, just look in the window object and any local scope
// (reading into JS mode internals to get at the local variables)
// (reading into JS mode internals to get at the local and global variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
gatherCompletions(window);
forEach(keywords, maybeAdd);
}

@ -16,7 +16,7 @@
return arr.indexOf(item) != -1;
}
function scriptHint(editor, keywords, getToken) {
function scriptHint(editor, _keywords, getToken) {
// Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
// If it's not a 'word-style' token, ignore the token.
@ -45,12 +45,6 @@
return scriptHint(editor, pigKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
};
function toTitleCase(str) {
return str.replace(/(?:^|\s)\w/g, function(match) {
return match.toUpperCase();
});
}
var pigKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP "
+ "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL "
+ "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE "
@ -109,9 +103,9 @@
// find in the current environment.
var obj = context.pop(), base;
if (obj.className == "pig-word")
if (obj.type == "variable")
base = obj.string;
else if(obj.className == "pig-type")
else if(obj.type == "variable-3")
base = ":" + obj.string;
while (base != null && context.length)

@ -0,0 +1,93 @@
(function () {
function forEach(arr, f) {
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
}
function arrayContains(arr, item) {
if (!Array.prototype.indexOf) {
var i = arr.length;
while (i--) {
if (arr[i] === item) {
return true;
}
}
return false;
}
return arr.indexOf(item) != -1;
}
function scriptHint(editor, _keywords, getToken) {
// Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
// If it's not a 'word-style' token, ignore the token.
if (!/^[\w$_]*$/.test(token.string)) {
token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
className: token.string == ":" ? "python-type" : null};
}
if (!context) var context = [];
context.push(tprop);
var completionList = getCompletions(token, context);
completionList = completionList.sort();
//prevent autocomplete for last word, instead show dropdown with one word
if(completionList.length == 1) {
completionList.push(" ");
}
return {list: completionList,
from: {line: cur.line, ch: token.start},
to: {line: cur.line, ch: token.end}};
}
CodeMirror.pythonHint = function(editor) {
return scriptHint(editor, pythonKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
};
var pythonKeywords = "and del from not while as elif global or with assert else if pass yield"
+ "break except import print class exec in raise continue finally is return def for lambda try";
var pythonKeywordsL = pythonKeywords.split(" ");
var pythonKeywordsU = pythonKeywords.toUpperCase().split(" ");
var pythonBuiltins = "abs divmod input open staticmethod all enumerate int ord str "
+ "any eval isinstance pow sum basestring execfile issubclass print super"
+ "bin file iter property tuple bool filter len range type"
+ "bytearray float list raw_input unichr callable format locals reduce unicode"
+ "chr frozenset long reload vars classmethod getattr map repr xrange"
+ "cmp globals max reversed zip compile hasattr memoryview round __import__"
+ "complex hash min set apply delattr help next setattr buffer"
+ "dict hex object slice coerce dir id oct sorted intern ";
var pythonBuiltinsL = pythonBuiltins.split(" ").join("() ").split(" ");
var pythonBuiltinsU = pythonBuiltins.toUpperCase().split(" ").join("() ").split(" ");
function getCompletions(token, context) {
var found = [], start = token.string;
function maybeAdd(str) {
if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
}
function gatherCompletions(_obj) {
forEach(pythonBuiltinsL, maybeAdd);
forEach(pythonBuiltinsU, maybeAdd);
forEach(pythonKeywordsL, maybeAdd);
forEach(pythonKeywordsU, maybeAdd);
}
if (context) {
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.type == "variable")
base = obj.string;
else if(obj.type == "variable-3")
base = ":" + obj.string;
while (base != null && context.length)
base = base[context.pop().string];
if (base != null) gatherCompletions(base);
}
return found;
}
})();

@ -14,18 +14,21 @@
// Don't show completions if token has changed and the option is set.
if (options.closeOnTokenChange && previousToken != null &&
(tempToken.start != previousToken.start || tempToken.className != previousToken.className)) {
(tempToken.start != previousToken.start || tempToken.type != previousToken.type)) {
return;
}
var result = getHints(editor);
var result = getHints(editor, givenOptions);
if (!result || !result.list.length) return;
var completions = result.list;
function insert(str) {
editor.replaceRange(str, result.from, result.to);
}
// When there is only one completion, use it directly.
if (completions.length == 1) {insert(completions[0]); return true;}
if (options.completeSingle && completions.length == 1) {
insert(completions[0]);
return true;
}
// Build the select widget
var complete = document.createElement("div");
@ -41,14 +44,14 @@
}
sel.firstChild.selected = true;
sel.size = Math.min(10, completions.length);
var pos = editor.cursorCoords();
complete.style.left = pos.x + "px";
complete.style.top = pos.yBot + "px";
var pos = editor.cursorCoords(options.alignWithWord ? result.from : null);
complete.style.left = pos.left + "px";
complete.style.top = pos.bottom + "px";
document.body.appendChild(complete);
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
if(winW - pos.x < sel.clientWidth)
complete.style.left = (pos.x - sel.clientWidth) + "px";
if(winW - pos.left < sel.clientWidth)
complete.style.left = (pos.left - sel.clientWidth) + "px";
// Hack to hide the scrollbar.
if (completions.length <= 10)
complete.style.width = (sel.clientWidth - 1) + "px";
@ -64,14 +67,14 @@
close();
setTimeout(function(){editor.focus();}, 50);
}
CodeMirror.connect(sel, "blur", close);
CodeMirror.connect(sel, "keydown", function(event) {
CodeMirror.on(sel, "blur", close);
CodeMirror.on(sel, "keydown", function(event) {
var code = event.keyCode;
// Enter
if (code == 13) {CodeMirror.e_stop(event); pick();}
// Escape
else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
else if (code != 38 && code != 40 && code != 33 && code != 34) {
else if (code != 38 && code != 40 && code != 33 && code != 34 && !CodeMirror.isModifierKey(event)) {
close(); editor.focus();
// Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
editor.triggerOnKeyDown(event);
@ -81,7 +84,7 @@
}
}
});
CodeMirror.connect(sel, "dblclick", pick);
CodeMirror.on(sel, "dblclick", pick);
sel.focus();
// Opera sometimes ignores focusing a freshly created node
@ -92,6 +95,8 @@
};
CodeMirror.simpleHint.defaults = {
closeOnBackspace: true,
closeOnTokenChange: false
closeOnTokenChange: false,
completeSingle: true,
alignWithWord: true
};
})();

@ -12,13 +12,7 @@
cm.setCursor(cursor);
}
// dirty hack for simple-hint to receive getHint event on space
var getTokenAt = editor.getTokenAt;
editor.getTokenAt = function() { return 'disabled'; };
CodeMirror.simpleHint(cm, getHint);
editor.getTokenAt = getTokenAt;
};
var getHint = function(cm) {
@ -42,7 +36,7 @@
text = text.slice(0, text.length - typed.length);
var path = getActiveElement(cm, text) + simbol;
var path = getActiveElement(text) + simbol;
var hints = CodeMirror.xmlHints[path];
if(typeof hints === 'undefined')
@ -63,7 +57,7 @@
};
};
var getActiveElement = function(codeMirror, text) {
var getActiveElement = function(text) {
var element = '';

@ -68,6 +68,24 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
},
blankLine: function(state) {
var mode = state.innerActive ? state.innerActive.mode : outer;
if (mode.blankLine) {
mode.blankLine(state.innerActive ? state.inner : state.outer);
}
if (!state.innerActive) {
for (var i = 0; i < n_others; ++i) {
var other = others[i];
if (other.open === "\n") {
state.innerActive = other;
state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
}
}
} else if (mode.close === "\n") {
state.innerActive = state.inner = null;
}
},
electricChars: outer.electricChars,
innerMode: function(state) {

@ -49,6 +49,11 @@ CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, comb
},
electricChars: base.electricChars,
innerMode: function(state) { return {state: state.base, mode: base}; }
innerMode: function(state) { return {state: state.base, mode: base}; },
blankLine: function(state) {
if (base.blankLine) base.blankLine(state.base);
if (overlay.blankLine) overlay.blankLine(state.overlay);
}
};
};

@ -0,0 +1,29 @@
CodeMirror.colorize = (function() {
var isBlock = /^(p|li|div|h\\d|pre|blockquote|td)$/;