Adding change to init update in PM

This commit is contained in:
ralph
2013-03-28 15:44:44 -04:00
parent ee476fd642
commit 44b4cd860c
35 changed files with 2988 additions and 8 deletions

View File

@@ -0,0 +1,32 @@
.CodeMirror-dialog {
position: absolute;
left: 0; right: 0;
background: white;
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;
background: transparent;
width: 20em;
color: inherit;
font-family: monospace;
}
.CodeMirror-dialog button {
font-size: 70%;
}

View File

@@ -0,0 +1,80 @@
// Open simple dialogs on top of an editor. Relies on dialog.css.
(function() {
function dialogDiv(cm, template, bottom) {
var wrap = cm.getWrapperElement();
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, options) {
var dialog = dialogDiv(this, template, options && options.bottom);
var closed = false, me = this;
function close() {
if (closed) return;
closed = true;
dialog.parentNode.removeChild(dialog);
}
var inp = dialog.getElementsByTagName("input")[0], button;
if (inp) {
CodeMirror.on(inp, "keydown", function(e) {
if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
if (e.keyCode == 13 || e.keyCode == 27) {
CodeMirror.e_stop(e);
close();
me.focus();
if (e.keyCode == 13) callback(inp.value);
}
});
if (options && options.onKeyUp) {
CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
}
if (options && options.value) inp.value = options.value;
inp.focus();
CodeMirror.on(inp, "blur", close);
} else if (button = dialog.getElementsByTagName("button")[0]) {
CodeMirror.on(button, "click", function() {
close();
me.focus();
});
button.focus();
CodeMirror.on(button, "blur", close);
}
return close;
});
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() {
if (closed) return;
closed = true;
dialog.parentNode.removeChild(dialog);
me.focus();
}
buttons[0].focus();
for (var i = 0; i < buttons.length; ++i) {
var b = buttons[i];
(function(callback) {
CodeMirror.on(b, "click", function(e) {
CodeMirror.e_preventDefault(e);
close();
if (callback) callback(me);
});
})(callbacks[i]);
CodeMirror.on(b, "blur", function() {
--blurring;
setTimeout(function() { if (blurring <= 0) close(); }, 200);
});
CodeMirror.on(b, "focus", function() { ++blurring; });
}
});
})();

View File

@@ -0,0 +1,54 @@
(function() {
CodeMirror.defineOption("placeholder", "", function(cm, val, old) {
var prev = old && old != CodeMirror.Init;
if (val && !prev) {
cm.on("focus", onFocus);
cm.on("blur", onBlur);
cm.on("change", onChange);
onChange(cm);
} else if (!val && prev) {
cm.off("focus", onFocus);
cm.off("blur", onBlur);
cm.off("change", onChange);
clearPlaceholder(cm);
var wrapper = cm.getWrapperElement();
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
}
if (val && !cm.hasFocus()) onBlur(cm);
});
function clearPlaceholder(cm) {
if (cm._placeholder) {
cm._placeholder.parentNode.removeChild(cm._placeholder);
cm._placeholder = null;
}
}
function setPlaceholder(cm) {
clearPlaceholder(cm);
var elt = cm._placeholder = document.createElement("pre");
elt.style.cssText = "height: 0; overflow: visible";
elt.className = "CodeMirror-placeholder";
elt.appendChild(document.createTextNode(cm.getOption("placeholder")));
cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
}
function onFocus(cm) {
clearPlaceholder(cm);
}
function onBlur(cm) {
if (isEmpty(cm)) setPlaceholder(cm);
}
function onChange(cm) {
var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : "");
if (cm.hasFocus()) return;
if (empty) setPlaceholder(cm);
else clearPlaceholder(cm);
}
function isEmpty(cm) {
return (cm.lineCount() === 1) && (cm.getLine(0) === "");
}
})();

View File

@@ -0,0 +1,52 @@
(function() {
var DEFAULT_BRACKETS = "()[]{}''\"\"";
var SPACE_CHAR_REGEX = /\s/;
CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
var wasOn = old && old != CodeMirror.Init;
if (val && !wasOn)
cm.addKeyMap(buildKeymap(typeof val == "string" ? val : DEFAULT_BRACKETS));
else if (!val && wasOn)
cm.removeKeyMap("autoCloseBrackets");
});
function buildKeymap(pairs) {
var map = {
name : "autoCloseBrackets",
Backspace: function(cm) {
if (cm.somethingSelected()) return CodeMirror.Pass;
var cur = cm.getCursor(), line = cm.getLine(cur.line);
if (cur.ch && cur.ch < line.length &&
pairs.indexOf(line.slice(cur.ch - 1, cur.ch + 1)) % 2 == 0)
cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1));
else
return CodeMirror.Pass;
}
};
var closingBrackets = [];
for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
if (left != right) closingBrackets.push(right);
function surround(cm) {
var selection = cm.getSelection();
cm.replaceSelection(left + selection + right);
}
function maybeOverwrite(cm) {
var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1));
if (ahead != right || cm.somethingSelected()) return CodeMirror.Pass;
else cm.execCommand("goCharRight");
}
map["'" + left + "'"] = function(cm) {
if (cm.somethingSelected()) return surround(cm);
if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return;
var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1);
var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch);
if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || SPACE_CHAR_REGEX.test(nextChar))
cm.replaceSelection(left + right, {head: ahead, anchor: ahead});
else
return CodeMirror.Pass;
};
if (left != right) map["'" + right + "'"] = maybeOverwrite;
})(pairs.charAt(i), pairs.charAt(i + 1));
return map;
}
})();

View File

@@ -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) { return autoCloseTag(cm, '/'); };
if (typeof val != "object" || val.whenOpening)
map["'>'"] = function(cm) { return 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") return 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" || tok.string.indexOf("/") > -1 ||
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1)
return CodeMirror.Pass;
var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1;
var curPos = doIndent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1);
cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "</" + tagName + ">",
{head: curPos, anchor: curPos});
if (doIndent) {
cm.indentLine(pos.line + 1);
cm.indentLine(pos.line + 2);
}
return;
} else if (ch == "/" && tok.string == "<") {
var tagName = state.context && state.context.tagName;
if (tagName) cm.replaceSelection("/" + tagName + ">", "end");
return;
}
return 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;
}
})();

View File

@@ -0,0 +1,44 @@
(function() {
var modes = ["clike", "css", "javascript"];
for (var i = 0; i < modes.length; ++i)
CodeMirror.extendMode(modes[i], {blockCommentStart: "/*",
blockCommentEnd: "*/",
blockCommentContinue: " * "});
function continueComment(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(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, 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
return CodeMirror.Pass;
}
CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
if (prev && prev != CodeMirror.Init)
cm.removeKeyMap("continueComment");
var map = {name: "continueComment"};
map[typeof val == "string" ? val : "Enter"] = continueComment;
cm.addKeyMap(map);
});
})();

View File

@@ -0,0 +1,25 @@
(function() {
'use strict';
var listRE = /^(\s*)([*+-]|(\d+)\.)(\s*)/,
unorderedBullets = '*+-';
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
var pos = cm.getCursor(),
inList = cm.getStateAfter(pos.line).list,
match;
if (!inList || !(match = cm.getLine(pos.line).match(listRE))) {
cm.execCommand('newlineAndIndent');
return;
}
var indent = match[1], after = match[4];
var bullet = unorderedBullets.indexOf(match[2]) >= 0
? match[2]
: (parseInt(match[3], 10) + 1) + '.';
cm.replaceSelection('\n' + indent + bullet + after, 'end');
};
}());

View File

@@ -0,0 +1,74 @@
(function() {
var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
(document.documentMode == null || document.documentMode < 8);
var Pos = CodeMirror.Pos;
// Disable brace matching in long lines, since it'll cause hugely slow updates
var maxLineLen = 1000;
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(Pos(cur.line, 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(Pos(lineNo, 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: Pos(cur.line, pos), to: found && Pos(i, found.pos), match: found && found.match};
}
function matchBrackets(cm, autoclear) {
var found = findMatchingBracket(cm);
if (!found || cm.getLine(found.from.line).length > maxLineLen ||
found.to && cm.getLine(found.to.line).length > maxLineLen)
return;
var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style});
var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style});
// Kludge to work around the IE bug from issue #1193, where text
// input stops going to the textare whever this fires.
if (ie_lt8 && cm.state.focused) cm.display.input.focus();
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);});
})();

View File

@@ -0,0 +1,31 @@
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 < start.ch) break;
tokenType = cm.getTokenAt(CodeMirror.Pos(line, found + 1)).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, endCh;
outer: for (var i = line + 1; i < lastLine; ++i) {
var text = cm.getLine(i), pos = 0;
for (;;) {
var nextOpen = text.indexOf("{", pos), nextClose = text.indexOf("}", pos);
if (nextOpen < 0) nextOpen = text.length;
if (nextClose < 0) nextClose = text.length;
pos = Math.min(nextOpen, nextClose);
if (pos == text.length) break;
if (cm.getTokenAt(CodeMirror.Pos(i, pos + 1)).type == tokenType) {
if (pos == nextOpen) ++count;
else if (!--count) { end = i; endCh = pos; break outer; }
}
++pos;
}
}
if (end == null || end == line + 1) return;
return {from: CodeMirror.Pos(line, startChar + 1),
to: CodeMirror.Pos(end, endCh)};
};

View File

@@ -0,0 +1,32 @@
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";
}
return function(cm, pos) {
if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
var range = rangeFinder(cm, pos);
if (!range) return;
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
});
};
};

View File

@@ -0,0 +1,11 @@
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: CodeMirror.Pos(start.line, firstLine.length),
to: CodeMirror.Pos(i, curLine.length)};
}
};

View File

@@ -0,0 +1,64 @@
CodeMirror.tagRangeFinder = (function() {
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 xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g");
return function(cm, start) {
var line = start.line, ch = start.ch, lineText = cm.getLine(line);
function nextLine() {
if (line >= cm.lastLine()) return;
ch = 0;
lineText = cm.getLine(++line);
return true;
}
function toTagEnd() {
for (;;) {
var gt = lineText.indexOf(">", ch);
if (gt == -1) { if (nextLine()) continue; else return; }
var lastSlash = lineText.lastIndexOf("/", gt);
var selfClose = lastSlash > -1 && /^\s*$/.test(lineText.slice(lastSlash + 1, gt));
ch = gt + 1;
return selfClose ? "selfClose" : "regular";
}
}
function toNextTag() {
for (;;) {
xmlTagStart.lastIndex = ch;
var found = xmlTagStart.exec(lineText);
if (!found) { if (nextLine()) continue; else return; }
ch = found.index + found[0].length;
return found;
}
}
var stack = [], startCh;
for (;;) {
var openTag = toNextTag(), end;
if (!openTag || line != start.line || !(end = toTagEnd())) return;
if (!openTag[1] && end != "selfClose") {
stack.push(openTag[2]);
startCh = ch;
break;
}
}
for (;;) {
var next = toNextTag(), end, tagLine = line, tagCh = ch - (next ? next[0].length : 0);
if (!next || !(end = toTagEnd())) return;
if (end == "selfClose") continue;
if (next[1]) { // closing tag
for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) {
stack.length = i;
break;
}
if (!stack.length) return {
from: CodeMirror.Pos(start.line, startCh),
to: CodeMirror.Pos(tagLine, tagCh)
};
} else { // opening tag
stack.push(next[2]);
}
}
};
})();

582
gulliver/js/codemirror/addon/hint/html-hint.js vendored Executable file
View File

@@ -0,0 +1,582 @@
(function () {
function htmlHint(editor, htmlStructure, getToken) {
var cur = editor.getCursor();
var token = getToken(editor, cur);
var keywords = [];
var i = 0;
var j = 0;
var k = 0;
var from = {line: cur.line, ch: cur.ch};
var to = {line: cur.line, ch: cur.ch};
var flagClean = true;
var text = editor.getRange({line: 0, ch: 0}, cur);
var open = text.lastIndexOf('<');
var close = text.lastIndexOf('>');
var tokenString = token.string.replace("<","");
if(open > close) {
var last = editor.getRange({line: cur.line, ch: cur.ch - 1}, cur);
if(last == "<") {
for(i = 0; i < htmlStructure.length; i++) {
keywords.push(htmlStructure[i].tag);
}
from.ch = token.start + 1;
} else {
var counter = 0;
var found = function(token, type, position) {
counter++;
if(counter > 50) return;
if(token.type == type) {
return token;
} else {
position.ch = token.start;
var newToken = editor.getTokenAt(position);
return found(newToken, type, position);
}
};
var nodeToken = found(token, "tag", {line: cur.line, ch: cur.ch});
var node = nodeToken.string.substring(1);
if(token.type === null && token.string.trim() === "") {
for(i = 0; i < htmlStructure.length; i++) {
if(htmlStructure[i].tag == node) {
for(j = 0; j < htmlStructure[i].attr.length; j++) {
keywords.push(htmlStructure[i].attr[j].key + "=\"\" ");
}
for(k = 0; k < globalAttributes.length; k++) {
keywords.push(globalAttributes[k].key + "=\"\" ");
}
}
}
} else if(token.type == "string") {
tokenString = tokenString.substring(1, tokenString.length - 1);
var attributeToken = found(token, "attribute", {line: cur.line, ch: cur.ch});
var attribute = attributeToken.string;
for(i = 0; i < htmlStructure.length; i++) {
if(htmlStructure[i].tag == node) {
for(j = 0; j < htmlStructure[i].attr.length; j++) {
if(htmlStructure[i].attr[j].key == attribute) {
for(k = 0; k < htmlStructure[i].attr[j].values.length; k++) {
keywords.push(htmlStructure[i].attr[j].values[k]);
}
}
}
for(j = 0; j < globalAttributes.length; j++) {
if(globalAttributes[j].key == attribute) {
for(k = 0; k < globalAttributes[j].values.length; k++) {
keywords.push(globalAttributes[j].values[k]);
}
}
}
}
}
from.ch = token.start + 1;
} else if(token.type == "attribute") {
for(i = 0; i < htmlStructure.length; i++) {
if(htmlStructure[i].tag == node) {
for(j = 0; j < htmlStructure[i].attr.length; j++) {
keywords.push(htmlStructure[i].attr[j].key + "=\"\" ");
}
for(k = 0; k < globalAttributes.length; k++) {
keywords.push(globalAttributes[k].key + "=\"\" ");
}
}
}
from.ch = token.start;
} else if(token.type == "tag") {
for(i = 0; i < htmlStructure.length; i++) {
keywords.push(htmlStructure[i].tag);
}
from.ch = token.start + 1;
}
}
} else {
for(i = 0; i < htmlStructure.length; i++) {
keywords.push("<" + htmlStructure[i].tag);
}
tokenString = ("<" + tokenString).trim();
from.ch = token.start;
}
if(flagClean === true && tokenString.trim() === "") {
flagClean = false;
}
if(flagClean) {
keywords = cleanResults(tokenString, keywords);
}
return {list: keywords, from: from, to: to};
}
var cleanResults = function(text, keywords) {
var results = [];
var i = 0;
for(i = 0; i < keywords.length; i++) {
if(keywords[i].substring(0, text.length) == text) {
results.push(keywords[i]);
}
}
return results;
};
var htmlStructure = [
{tag: '!DOCTYPE', attr: []},
{tag: 'a', attr: [
{key: 'href', values: ["#"]},
{key: 'target', values: ["_blank","_self","_top","_parent"]},
{key: 'ping', values: [""]},
{key: 'media', values: ["#"]},
{key: 'hreflang', values: ["en","es"]},
{key: 'type', values: []}
]},
{tag: 'abbr', attr: []},
{tag: 'acronym', attr: []},
{tag: 'address', attr: []},
{tag: 'applet', attr: []},
{tag: 'area', attr: [
{key: 'alt', values: [""]},
{key: 'coords', values: ["rect: left, top, right, bottom","circle: center-x, center-y, radius","poly: x1, y1, x2, y2, ..."]},
{key: 'shape', values: ["default","rect","circle","poly"]},
{key: 'href', values: ["#"]},
{key: 'target', values: ["#"]},
{key: 'ping', values: []},
{key: 'media', values: []},
{key: 'hreflang', values: []},
{key: 'type', values: []}
]},
{tag: 'article', attr: []},
{tag: 'aside', attr: []},
{tag: 'audio', attr: [
{key: 'src', values: []},
{key: 'crossorigin', values: ["anonymous","use-credentials"]},
{key: 'preload', values: ["none","metadata","auto"]},
{key: 'autoplay', values: ["","autoplay"]},
{key: 'mediagroup', values: []},
{key: 'loop', values: ["","loop"]},
{key: 'controls', values: ["","controls"]}
]},
{tag: 'b', attr: []},
{tag: 'base', attr: [
{key: 'href', values: ["#"]},
{key: 'target', values: ["_blank","_self","_top","_parent"]}
]},
{tag: 'basefont', attr: []},
{tag: 'bdi', attr: []},
{tag: 'bdo', attr: []},
{tag: 'big', attr: []},
{tag: 'blockquote', attr: [
{key: 'cite', values: ["http://"]}
]},
{tag: 'body', attr: []},
{tag: 'br', attr: []},
{tag: 'button', attr: [
{key: 'autofocus', values: ["","autofocus"]},
{key: 'disabled', values: ["","disabled"]},
{key: 'form', values: []},
{key: 'formaction', values: []},
{key: 'formenctype', values: ["application/x-www-form-urlencoded","multipart/form-data","text/plain"]},
{key: 'formmethod', values: ["get","post","put","delete"]},
{key: 'formnovalidate', values: ["","novalidate"]},
{key: 'formtarget', values: ["_blank","_self","_top","_parent"]},
{key: 'name', values: []},
{key: 'type', values: ["submit","reset","button"]},
{key: 'value', values: []}
]},
{tag: 'canvas', attr: [
{key: 'width', values: []},
{key: 'height', values: []}
]},
{tag: 'caption', attr: []},
{tag: 'center', attr: []},
{tag: 'cite', attr: []},
{tag: 'code', attr: []},
{tag: 'col', attr: [
{key: 'span', values: []}
]},
{tag: 'colgroup', attr: [
{key: 'span', values: []}
]},
{tag: 'command', attr: [
{key: 'type', values: ["command","checkbox","radio"]},
{key: 'label', values: []},
{key: 'icon', values: []},
{key: 'disabled', values: ["","disabled"]},
{key: 'checked', values: ["","checked"]},
{key: 'radiogroup', values: []},
{key: 'command', values: []},
{key: 'title', values: []}
]},
{tag: 'data', attr: [
{key: 'value', values: []}
]},
{tag: 'datagrid', attr: [
{key: 'disabled', values: ["","disabled"]},
{key: 'multiple', values: ["","multiple"]}
]},
{tag: 'datalist', attr: [
{key: 'data', values: []}
]},
{tag: 'dd', attr: []},
{tag: 'del', attr: [
{key: 'cite', values: []},
{key: 'datetime', values: []}
]},
{tag: 'details', attr: [
{key: 'open', values: ["","open"]}
]},
{tag: 'dfn', attr: []},
{tag: 'dir', attr: []},
{tag: 'div', attr: [
{key: 'id', values: []},
{key: 'class', values: []},
{key: 'style', values: []}
]},
{tag: 'dl', attr: []},
{tag: 'dt', attr: []},
{tag: 'em', attr: []},
{tag: 'embed', attr: [
{key: 'src', values: []},
{key: 'type', values: []},
{key: 'width', values: []},
{key: 'height', values: []}
]},
{tag: 'eventsource', attr: [
{key: 'src', values: []}
]},
{tag: 'fieldset', attr: [
{key: 'disabled', values: ["","disabled"]},
{key: 'form', values: []},
{key: 'name', values: []}
]},
{tag: 'figcaption', attr: []},
{tag: 'figure', attr: []},
{tag: 'font', attr: []},
{tag: 'footer', attr: []},
{tag: 'form', attr: [
{key: 'accept-charset', values: ["UNKNOWN","utf-8"]},
{key: 'action', values: []},
{key: 'autocomplete', values: ["on","off"]},
{key: 'enctype', values: ["application/x-www-form-urlencoded","multipart/form-data","text/plain"]},
{key: 'method', values: ["get","post","put","delete","dialog"]},
{key: 'name', values: []},
{key: 'novalidate', values: ["","novalidate"]},
{key: 'target', values: ["_blank","_self","_top","_parent"]}
]},
{tag: 'frame', attr: []},
{tag: 'frameset', attr: []},
{tag: 'h1', attr: []},
{tag: 'h2', attr: []},
{tag: 'h3', attr: []},
{tag: 'h4', attr: []},
{tag: 'h5', attr: []},
{tag: 'h6', attr: []},
{tag: 'head', attr: []},
{tag: 'header', attr: []},
{tag: 'hgroup', attr: []},
{tag: 'hr', attr: []},
{tag: 'html', attr: [
{key: 'manifest', values: []}
]},
{tag: 'i', attr: []},
{tag: 'iframe', attr: [
{key: 'src', values: []},
{key: 'srcdoc', values: []},
{key: 'name', values: []},
{key: 'sandbox', values: ["allow-top-navigation","allow-same-origin","allow-forms","allow-scripts"]},
{key: 'seamless', values: ["","seamless"]},
{key: 'width', values: []},
{key: 'height', values: []}
]},
{tag: 'img', attr: [
{key: 'alt', values: []},
{key: 'src', values: []},
{key: 'crossorigin', values: ["anonymous","use-credentials"]},
{key: 'ismap', values: []},
{key: 'usemap', values: []},
{key: 'width', values: []},
{key: 'height', values: []}
]},
{tag: 'input', attr: [
{key: 'accept', values: ["audio/*","video/*","image/*"]},
{key: 'alt', values: []},
{key: 'autocomplete', values: ["on","off"]},
{key: 'autofocus', values: ["","autofocus"]},
{key: 'checked', values: ["","checked"]},
{key: 'disabled', values: ["","disabled"]},
{key: 'dirname', values: []},
{key: 'form', values: []},
{key: 'formaction', values: []},
{key: 'formenctype', values: ["application/x-www-form-urlencoded","multipart/form-data","text/plain"]},
{key: 'formmethod', values: ["get","post","put","delete"]},
{key: 'formnovalidate', values: ["","novalidate"]},
{key: 'formtarget', values: ["_blank","_self","_top","_parent"]},
{key: 'height', values: []},
{key: 'list', values: []},
{key: 'max', values: []},
{key: 'maxlength', values: []},
{key: 'min', values: []},
{key: 'multiple', values: ["","multiple"]},
{key: 'name', values: []},
{key: 'pattern', values: []},
{key: 'placeholder', values: []},
{key: 'readonly', values: ["","readonly"]},
{key: 'required', values: ["","required"]},
{key: 'size', values: []},
{key: 'src', values: []},
{key: 'step', values: []},
{key: 'type', values: [
"hidden","text","search","tel","url","email","password","datetime","date","month","week","time","datetime-local",
"number","range","color","checkbox","radio","file","submit","image","reset","button"
]},
{key: 'value', values: []},
{key: 'width', values: []}
]},
{tag: 'ins', attr: [
{key: 'cite', values: []},
{key: 'datetime', values: []}
]},
{tag: 'kbd', attr: []},
{tag: 'keygen', attr: [
{key: 'autofocus', values: ["","autofocus"]},
{key: 'challenge', values: []},
{key: 'disabled', values: ["","disabled"]},
{key: 'form', values: []},
{key: 'keytype', values: ["RSA"]},
{key: 'name', values: []}
]},
{tag: 'label', attr: [
{key: 'for', values: []},
{key: 'form', values: []}
]},
{tag: 'legend', attr: []},
{tag: 'li', attr: [
{key: 'value', values: []}
]},
{tag: 'link', attr: [
{key: 'href', values: []},
{key: 'hreflang', values: ["en","es"]},
{key: 'media', values: [
"all","screen","print","embossed","braille","handheld","print","projection","screen","tty","tv","speech","3d-glasses",
"resolution [>][<][=] [X]dpi","resolution [>][<][=] [X]dpcm","device-aspect-ratio: 16/9","device-aspect-ratio: 4/3",
"device-aspect-ratio: 32/18","device-aspect-ratio: 1280/720","device-aspect-ratio: 2560/1440","orientation:portrait",
"orientation:landscape","device-height: [X]px","device-width: [X]px","-webkit-min-device-pixel-ratio: 2"
]},
{key: 'type', values: []},
{key: 'sizes', values: ["all","16x16","16x16 32x32","16x16 32x32 64x64"]}
]},
{tag: 'map', attr: [
{key: 'name', values: []}
]},
{tag: 'mark', attr: []},
{tag: 'menu', attr: [
{key: 'type', values: ["list","context","toolbar"]},
{key: 'label', values: []}
]},
{tag: 'meta', attr: [
{key: 'charset', attr: ["utf-8"]},
{key: 'name', attr: ["viewport","application-name","author","description","generator","keywords"]},
{key: 'content', attr: ["","width=device-width","initial-scale=1, maximum-scale=1, minimun-scale=1, user-scale=no"]},
{key: 'http-equiv', attr: ["content-language","content-type","default-style","refresh"]}
]},
{tag: 'meter', attr: [
{key: 'value', values: []},
{key: 'min', values: []},
{key: 'low', values: []},
{key: 'high', values: []},
{key: 'max', values: []},
{key: 'optimum', values: []}
]},
{tag: 'nav', attr: []},
{tag: 'noframes', attr: []},
{tag: 'noscript', attr: []},
{tag: 'object', attr: [
{key: 'data', values: []},
{key: 'type', values: []},
{key: 'typemustmatch', values: ["","typemustmatch"]},
{key: 'name', values: []},
{key: 'usemap', values: []},
{key: 'form', values: []},
{key: 'width', values: []},
{key: 'height', values: []}
]},
{tag: 'ol', attr: [
{key: 'reversed', values: ["", "reversed"]},
{key: 'start', values: []},
{key: 'type', values: ["1","a","A","i","I"]}
]},
{tag: 'optgroup', attr: [
{key: 'disabled', values: ["","disabled"]},
{key: 'label', values: []}
]},
{tag: 'option', attr: [
{key: 'disabled', values: ["", "disabled"]},
{key: 'label', values: []},
{key: 'selected', values: ["", "selected"]},
{key: 'value', values: []}
]},
{tag: 'output', attr: [
{key: 'for', values: []},
{key: 'form', values: []},
{key: 'name', values: []}
]},
{tag: 'p', attr: []},
{tag: 'param', attr: [
{key: 'name', values: []},
{key: 'value', values: []}
]},
{tag: 'pre', attr: []},
{tag: 'progress', attr: [
{key: 'value', values: []},
{key: 'max', values: []}
]},
{tag: 'q', attr: [
{key: 'cite', values: []}
]},
{tag: 'rp', attr: []},
{tag: 'rt', attr: []},
{tag: 'ruby', attr: []},
{tag: 's', attr: []},
{tag: 'samp', attr: []},
{tag: 'script', attr: [
{key: 'type', values: ["text/javascript"]},
{key: 'src', values: []},
{key: 'async', values: ["","async"]},
{key: 'defer', values: ["","defer"]},
{key: 'charset', values: ["utf-8"]}
]},
{tag: 'section', attr: []},
{tag: 'select', attr: [
{key: 'autofocus', values: ["", "autofocus"]},
{key: 'disabled', values: ["", "disabled"]},
{key: 'form', values: []},
{key: 'multiple', values: ["", "multiple"]},
{key: 'name', values: []},
{key: 'size', values: []}
]},
{tag: 'small', attr: []},
{tag: 'source', attr: [
{key: 'src', values: []},
{key: 'type', values: []},
{key: 'media', values: []}
]},
{tag: 'span', attr: []},
{tag: 'strike', attr: []},
{tag: 'strong', attr: []},
{tag: 'style', attr: [
{key: 'type', values: ["text/css"]},
{key: 'media', values: ["all","braille","print","projection","screen","speech"]},
{key: 'scoped', values: []}
]},
{tag: 'sub', attr: []},
{tag: 'summary', attr: []},
{tag: 'sup', attr: []},
{tag: 'table', attr: [
{key: 'border', values: []}
]},
{tag: 'tbody', attr: []},
{tag: 'td', attr: [
{key: 'colspan', values: []},
{key: 'rowspan', values: []},
{key: 'headers', values: []}
]},
{tag: 'textarea', attr: [
{key: 'autofocus', values: ["","autofocus"]},
{key: 'disabled', values: ["","disabled"]},
{key: 'dirname', values: []},
{key: 'form', values: []},
{key: 'maxlength', values: []},
{key: 'name', values: []},
{key: 'placeholder', values: []},
{key: 'readonly', values: ["","readonly"]},
{key: 'required', values: ["","required"]},
{key: 'rows', values: []},
{key: 'cols', values: []},
{key: 'wrap', values: ["soft","hard"]}
]},
{tag: 'tfoot', attr: []},
{tag: 'th', attr: [
{key: 'colspan', values: []},
{key: 'rowspan', values: []},
{key: 'headers', values: []},
{key: 'scope', values: ["row","col","rowgroup","colgroup"]}
]},
{tag: 'thead', attr: []},
{tag: 'time', attr: [
{key: 'datetime', values: []}
]},
{tag: 'title', attr: []},
{tag: 'tr', attr: []},
{tag: 'track', attr: [
{key: 'kind', values: ["subtitles","captions","descriptions","chapters","metadata"]},
{key: 'src', values: []},
{key: 'srclang', values: ["en","es"]},
{key: 'label', values: []},
{key: 'default', values: []}
]},
{tag: 'tt', attr: []},
{tag: 'u', attr: []},
{tag: 'ul', attr: []},
{tag: 'var', attr: []},
{tag: 'video', attr: [
{key: "src", values: []},
{key: "crossorigin", values: ["anonymous","use-credentials"]},
{key: "poster", values: []},
{key: "preload", values: ["auto","metadata","none"]},
{key: "autoplay", values: ["","autoplay"]},
{key: "mediagroup", values: ["movie"]},
{key: "loop", values: ["","loop"]},
{key: "muted", values: ["","muted"]},
{key: "controls", values: ["","controls"]},
{key: "width", values: []},
{key: "height", values: []}
]},
{tag: 'wbr', attr: []}
];
var globalAttributes = [
{key: "accesskey", values: ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9"]},
{key: "class", values: []},
{key: "contenteditable", values: ["true", "false"]},
{key: "contextmenu", values: []},
{key: "dir", values: ["ltr","rtl","auto"]},
{key: "draggable", values: ["true","false","auto"]},
{key: "dropzone", values: ["copy","move","link","string:","file:"]},
{key: "hidden", values: ["hidden"]},
{key: "id", values: []},
{key: "inert", values: ["inert"]},
{key: "itemid", values: []},
{key: "itemprop", values: []},
{key: "itemref", values: []},
{key: "itemscope", values: ["itemscope"]},
{key: "itemtype", values: []},
{key: "lang", values: ["en","es"]},
{key: "spellcheck", values: ["true","false"]},
{key: "style", values: []},
{key: "tabindex", values: ["1","2","3","4","5","6","7","8","9"]},
{key: "title", values: []},
{key: "translate", values: ["yes","no"]},
{key: "onclick", values: []},
{key: 'rel', values: ["stylesheet","alternate","author","bookmark","help","license","next","nofollow","noreferrer","prefetch","prev","search","tag"]}
];
CodeMirror.htmlHint = function(editor) {
if(String.prototype.trim == undefined) {
String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g, '');};
}
return htmlHint(editor, htmlStructure, function (e, cur) { return e.getTokenAt(cur); });
};
})();

View File

@@ -0,0 +1,140 @@
(function () {
var Pos = CodeMirror.Pos;
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, 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,
type: token.string == "." ? "property" : null};
}
// If it is a property, find out what it is a property of.
while (tprop.type == "property") {
tprop = getToken(editor, Pos(cur.line, tprop.start));
if (tprop.string != ".") return;
tprop = getToken(editor, Pos(cur.line, tprop.start));
if (tprop.string == ')') {
var level = 1;
do {
tprop = getToken(editor, Pos(cur.line, tprop.start));
switch (tprop.string) {
case ')': level++; break;
case '(': level--; break;
default: break;
}
} while (level > 0);
tprop = getToken(editor, Pos(cur.line, tprop.start));
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, options),
from: Pos(cur.line, token.start),
to: Pos(cur.line, token.end)};
}
CodeMirror.javascriptHint = function(editor, options) {
return scriptHint(editor, javascriptKeywords,
function (e, cur) {return e.getTokenAt(cur);},
options);
};
function getCoffeeScriptToken(editor, cur) {
// This getToken, it is for coffeescript, imitates the behavior of
// getTokenAt method in javascript.js, that is, returning "property"
// type and treat "." as indepenent token.
var token = editor.getTokenAt(cur);
if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
token.end = token.start;
token.string = '.';
token.type = "property";
}
else if (/^\.[\w$_]*$/.test(token.string)) {
token.type = "property";
token.start++;
token.string = token.string.replace(/\./, '');
}
return token;
}
CodeMirror.coffeescriptHint = function(editor, options) {
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
};
var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
"toUpperCase toLowerCase split concat match replace search").split(" ");
var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
"lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
var funcProps = "prototype apply call bind".split(" ");
var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
"if in instanceof new null return switch throw true try typeof var void while with").split(" ");
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, options) {
var found = [], start = token.string;
function maybeAdd(str) {
if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
}
function gatherCompletions(obj) {
if (typeof obj == "string") forEach(stringProps, maybeAdd);
else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
else if (obj instanceof Function) forEach(funcProps, maybeAdd);
for (var name in obj) maybeAdd(name);
}
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.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.type == "atom") {
base = 1;
} else if (obj.type == "function") {
if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
(typeof window.jQuery == 'function'))
base = window.jQuery();
else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function'))
base = window._();
}
while (base != null && context.length)
base = base[context.pop().string];
if (base != null) gatherCompletions(base);
}
else {
// If not, just look in the window object and any local scope
// (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);
}
return found;
}
})();

View File

@@ -0,0 +1,117 @@
(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 == ":" ? "pig-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: CodeMirror.Pos(cur.line, token.start),
to: CodeMirror.Pos(cur.line, token.end)};
}
CodeMirror.pigHint = function(editor) {
return scriptHint(editor, pigKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
};
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 "
+ "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE "
+ "NEQ MATCHES TRUE FALSE";
var pigKeywordsU = pigKeywords.split(" ");
var pigKeywordsL = pigKeywords.toLowerCase().split(" ");
var pigTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP";
var pigTypesU = pigTypes.split(" ");
var pigTypesL = pigTypes.toLowerCase().split(" ");
var pigBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL "
+ "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS "
+ "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG "
+ "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN "
+ "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER "
+ "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS "
+ "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA "
+ "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE "
+ "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG "
+ "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER";
var pigBuiltinsU = pigBuiltins.split(" ").join("() ").split(" ");
var pigBuiltinsL = pigBuiltins.toLowerCase().split(" ").join("() ").split(" ");
var pigBuiltinsC = ("BagSize BinStorage Bloom BuildBloom ConstantSize CubeDimensions DoubleAbs "
+ "DoubleAvg DoubleBase DoubleMax DoubleMin DoubleRound DoubleSum FloatAbs FloatAvg FloatMax "
+ "FloatMin FloatRound FloatSum GenericInvoker IntAbs IntAvg IntMax IntMin IntSum "
+ "InvokeForDouble InvokeForFloat InvokeForInt InvokeForLong InvokeForString Invoker "
+ "IsEmpty JsonLoader JsonMetadata JsonStorage LongAbs LongAvg LongMax LongMin LongSum MapSize "
+ "MonitoredUDF Nondeterministic OutputSchema PigStorage PigStreaming StringConcat StringMax "
+ "StringMin StringSize TextLoader TupleSize Utf8StorageConverter").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) {
if(obj == ":") {
forEach(pigTypesL, maybeAdd);
}
else {
forEach(pigBuiltinsU, maybeAdd);
forEach(pigBuiltinsL, maybeAdd);
forEach(pigBuiltinsC, maybeAdd);
forEach(pigTypesU, maybeAdd);
forEach(pigTypesL, maybeAdd);
forEach(pigKeywordsU, maybeAdd);
forEach(pigKeywordsL, 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;
}
})();

View File

@@ -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: CodeMirror.Pos(cur.line, token.start),
to: CodeMirror.Pos(cur.line, 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;
}
})();

View File

@@ -0,0 +1,118 @@
(function() {
CodeMirror.xmlHints = [];
CodeMirror.xmlHint = function(cm) {
var cursor = cm.getCursor();
if (cursor.ch > 0) {
var text = cm.getRange(CodeMirror.Pos(0, 0), cursor);
var typed = '';
var simbol = '';
for(var i = text.length - 1; i >= 0; i--) {
if(text[i] == ' ' || text[i] == '<') {
simbol = text[i];
break;
}
else {
typed = text[i] + typed;
}
}
text = text.slice(0, text.length - typed.length);
var path = getActiveElement(text) + simbol;
var hints = CodeMirror.xmlHints[path];
if(typeof hints === 'undefined')
hints = [''];
else {
hints = hints.slice(0);
for (var i = hints.length - 1; i >= 0; i--) {
if(hints[i].indexOf(typed) != 0)
hints.splice(i, 1);
}
}
return {
list: hints,
from: CodeMirror.Pos(cursor.line, cursor.ch - typed.length),
to: cursor
};
}
};
var getActiveElement = function(text) {
var element = '';
if(text.length >= 0) {
var regex = new RegExp('<([^!?][^\\s/>]*)[\\s\\S]*?>', 'g');
var matches = [];
var match;
while ((match = regex.exec(text)) != null) {
matches.push({
tag: match[1],
selfclose: (match[0].slice(match[0].length - 2) === '/>')
});
}
for (var i = matches.length - 1, skip = 0; i >= 0; i--) {
var item = matches[i];
if (item.tag[0] == '/')
{
skip++;
}
else if (item.selfclose == false)
{
if (skip > 0)
{
skip--;
}
else
{
element = '<' + item.tag + '>' + element;
}
}
}
element += getOpenTag(text);
}
return element;
};
var getOpenTag = function(text) {
var open = text.lastIndexOf('<');
var close = text.lastIndexOf('>');
if (close < open)
{
text = text.slice(open);
if(text != '<') {
var space = text.indexOf(' ');
if(space < 0)
space = text.indexOf('\t');
if(space < 0)
space = text.indexOf('\n');
if (space < 0)
space = text.length;
return text.slice(0, space);
}
}
return '';
};
})();

View File

@@ -0,0 +1,127 @@
(function() {
var bogus = [ "Dangerous comment" ];
var warnings = [ [ "Expected '{'",
"Statement body should be inside '{ }' braces." ] ];
var errors = [ "Missing semicolon", "Extra comma", "Missing property name",
"Unmatched ", " and instead saw", " is not defined",
"Unclosed string", "Stopping, unable to continue" ];
function validator(options, text) {
JSHINT(text, options);
var errors = JSHINT.data().errors, result = [];
if (errors) parseErrors(errors, result);
return result;
}
CodeMirror.javascriptValidatorWithOptions = function(options) {
return function(text) { return validator(options, text); };
};
CodeMirror.javascriptValidator = CodeMirror.javascriptValidatorWithOptions(null);
function cleanup(error) {
// All problems are warnings by default
fixWith(error, warnings, "warning", true);
fixWith(error, errors, "error");
return isBogus(error) ? null : error;
}
function fixWith(error, fixes, severity, force) {
var description, fix, find, replace, found;
description = error.description;
for ( var i = 0; i < fixes.length; i++) {
fix = fixes[i];
find = (typeof fix === "string" ? fix : fix[0]);
replace = (typeof fix === "string" ? null : fix[1]);
found = description.indexOf(find) !== -1;
if (force || found) {
error.severity = severity;
}
if (found && replace) {
error.description = replace;
}
}
}
function isBogus(error) {
var description = error.description;
for ( var i = 0; i < bogus.length; i++) {
if (description.indexOf(bogus[i]) !== -1) {
return true;
}
}
return false;
}
function parseErrors(errors, output) {
for ( var i = 0; i < errors.length; i++) {
var error = errors[i];
if (error) {
var linetabpositions, index;
linetabpositions = [];
// This next block is to fix a problem in jshint. Jshint
// replaces
// all tabs with spaces then performs some checks. The error
// positions (character/space) are then reported incorrectly,
// not taking the replacement step into account. Here we look
// at the evidence line and try to adjust the character position
// to the correct value.
if (error.evidence) {
// Tab positions are computed once per line and cached
var tabpositions = linetabpositions[error.line];
if (!tabpositions) {
var evidence = error.evidence;
tabpositions = [];
// ugggh phantomjs does not like this
// forEachChar(evidence, function(item, index) {
Array.prototype.forEach.call(evidence, function(item,
index) {
if (item === '\t') {
// First col is 1 (not 0) to match error
// positions
tabpositions.push(index + 1);
}
});
linetabpositions[error.line] = tabpositions;
}
if (tabpositions.length > 0) {
var pos = error.character;
tabpositions.forEach(function(tabposition) {
if (pos > tabposition) pos -= 1;
});
error.character = pos;
}
}
var start = error.character - 1, end = start + 1;
if (error.evidence) {
index = error.evidence.substring(start).search(/.\b/);
if (index > -1) {
end += index;
}
}
// Convert to format expected by validation service
error.description = error.reason;// + "(jshint)";
error.start = error.character;
error.end = end;
error = cleanup(error);
if (error)
output.push({message: error.description,
severity: error.severity,
from: CodeMirror.Pos(error.line - 1, start),
to: CodeMirror.Pos(error.line - 1, end)});
}
}
}
})();

View File

@@ -0,0 +1,14 @@
// Depends on jsonlint.js from https://github.com/zaach/jsonlint
CodeMirror.jsonValidator = function(text) {
var found = [];
jsonlint.parseError = function(str, hash) {
var loc = hash.loc;
found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),
to: CodeMirror.Pos(loc.last_line - 1, loc.last_column),
message: str});
};
try { jsonlint.parse(text); }
catch(e) {}
return found;
};

View File

@@ -0,0 +1,96 @@
/* The lint marker gutter */
.CodeMirror-lint-markers {
width: 16px;
}
.CodeMirror-lint-tooltip {
background-color: infobackground;
border: 1px solid black;
border-radius: 4px 4px 4px 4px;
color: infotext;
font-family: monospace;
font-size: 10pt;
overflow: hidden;
padding: 2px 5px;
position: fixed;
white-space: pre;
z-index: 100;
max-width: 600px;
opacity: 0;
transition: opacity .4s;
-moz-transition: opacity .4s;
-webkit-transition: opacity .4s;
-o-transition: opacity .4s;
-ms-transition: opacity .4s;
}
.CodeMirror-lint-span-error, .CodeMirror-lint-span-warning {
background-position: left bottom;
background-repeat: repeat-x;
}
.CodeMirror-lint-span-error {
background-image:
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")
;
}
.CodeMirror-lint-span-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {
background-position: center center;
background-repeat: no-repeat;
cursor: pointer;
display: inline-block;
height: 16px;
width: 16px;
vertical-align: middle;
position: relative;
}
.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {
padding-left: 18px;
background-position: top left;
background-repeat: no-repeat;
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAPVvcvWHiPVucvRuc+ttcfV6f91KVN5LU99PV/FZY/JhaM4oN84pONE4Rd1ATfJLWutVYPRgbdxpcsgWKMgZKs4lNfE/UvE/U+artcpdSc5uXveimslHPuBhW/eJhfV5efaCgO2CgP+/v+PExP///////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACUALAAAAAAQABAAAAZ+wJJwSCwaScgkySgkjTQZTkYzWhadnE5oE+pwqkSshwQqkzxfa4kkQXxEpA9J9EFI1KQGQQBAigYCBA14ExEWF0gXihETeA0QD3AkD5QQg0NsDnAJmwkOd5gYFSQKpXAFDBhqaxgLBwQBBAapq00YEg0UDRKqTGtKSL7Cw8JBADs=");
}
.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAP7bc//egf/ij/7ijv/jl/7kl//mnv7lnv/uwf7CTP7DTf7DT/7IW//Na/7Na//NbP7QdP/dmbltAIJNAF03AMSAJMSCLKqASa2DS6uBSquCSrGHTq6ETbCHT7WKUrKIUcCVXL+UXMOYX8GWXsSZYMiib6+ETbOIUcOXX86uhd3Muf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACsALAAAAAAQABAAAAZowJVwSCwaj0ihikRSJYcoBEL0XKlGkcjImQQhJBREKFnyICoThKeE/AAW6AXgdPyUAgrLJBEo0YsbAQyDhAEdRRwDDw8OaA4NDQImRBgFEJdglxAEGEQZKQcHBqOkKRpFF6mqq1WtrUEAOw==");
}
.CodeMirror-lint-marker-multiple {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJEAQvB2JVdrAAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAD1JREFUCNdtjkESADAEAzemf69f66HMqGlOIhYiFRFRtSQBWAY7mzx+EDTL6sSgb1jTk7Q87rxyqe37fXsAa78gLyZnRgEAAAAASUVORK5CYII=");
background-repeat: no-repeat;
background-position: right bottom;
width: 100%; height: 100%;
}
/* Styles for the overview ruler
.annotationOverview {
cursor: pointer;
border-radius: 2px;
left: 2px;
width: 8px;
}
.annotationOverview.error {
background-color: lightcoral;
border: 1px solid darkred;
}
.annotationOverview.warning {
background-color: Gold;
border: 1px solid black;
}
.annotationHTML.overlay {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJEAQvB2JVdrAAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAD1JREFUCNdtjkESADAEAzemf69f66HMqGlOIhYiFRFRtSQBWAY7mzx+EDTL6sSgb1jTk7Q87rxyqe37fXsAa78gLyZnRgEAAAAASUVORK5CYII=");
background-position: right bottom;
position: relative;
top: -16px;
}
*/

View File

@@ -0,0 +1,183 @@
CodeMirror.validate = (function() {
var GUTTER_ID = "CodeMirror-lint-markers";
var SEVERITIES = /^(?:error|warning)$/;
function showTooltip(e, content) {
var tt = document.createElement("div");
tt.className = "CodeMirror-lint-tooltip";
tt.appendChild(content.cloneNode(true));
document.body.appendChild(tt);
function position(e) {
if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
tt.style.top = (e.clientY - tt.offsetHeight - 5) + "px";
tt.style.left = (e.clientX + 5) + "px";
}
CodeMirror.on(document, "mousemove", position);
position(e);
tt.style.opacity = 1;
return tt;
}
function rm(elt) {
if (elt.parentNode) elt.parentNode.removeChild(elt);
}
function hideTooltip(tt) {
if (!tt.parentNode) return;
if (tt.style.opacity == null) rm(tt);
tt.style.opacity = 0;
setTimeout(function() { rm(tt); }, 600);
}
function LintState(cm, options, hasGutter) {
this.marked = [];
this.options = options;
this.timeout = null;
this.hasGutter = hasGutter;
this.onMouseOver = function(e) { onMouseOver(cm, e); };
}
function parseOptions(options) {
if (options instanceof Function) return {getAnnotations: options};
else if (!options || !options.getAnnotations) throw new Error("Required option 'getAnnotations' missing (lint addon)");
return options;
}
function clearMarks(cm) {
var state = cm._lintState;
if (state.hasGutter) cm.clearGutter(GUTTER_ID);
for (var i = 0; i < state.marked.length; ++i)
state.marked[i].clear();
state.marked.length = 0;
}
function makeMarker(labels, severity, multiple) {
var marker = document.createElement("div"), inner = marker;
marker.className = "CodeMirror-lint-marker-" + severity;
if (multiple) {
inner = marker.appendChild(document.createElement("div"));
inner.className = "CodeMirror-lint-marker-multiple";
}
var tooltip;
CodeMirror.on(inner, "mouseover", function(e) { tooltip = showTooltip(e, labels); });
CodeMirror.on(inner, "mouseout", function() { if (tooltip) hideTooltip(tooltip); });
return marker;
}
function getMaxSeverity(a, b) {
if (a == "error") return a;
else return b;
}
function groupByLine(annotations) {
var lines = [];
for (var i = 0; i < annotations.length; ++i) {
var ann = annotations[i], line = ann.from.line;
(lines[line] || (lines[line] = [])).push(ann);
}
return lines;
}
function annotationTooltip(ann) {
var severity = ann.severity;
if (!SEVERITIES.test(severity)) severity = "error";
var tip = document.createElement("div");
tip.className = "CodeMirror-lint-message-" + severity;
tip.appendChild(document.createTextNode(ann.message));
return tip;
}
function startLinting(cm) {
var state = cm._lintState, options = state.options;
if (options.async)
options.getAnnotations(cm, updateLinting, options);
else
updateLinting(cm, options.getAnnotations(cm.getValue()));
}
function updateLinting(cm, annotationsNotSorted) {
clearMarks(cm);
var state = cm._lintState, options = state.options;
var annotations = groupByLine(annotationsNotSorted);
for (var line = 0; line < annotations.length; ++line) {
var anns = annotations[line];
if (!anns) continue;
var maxSeverity = null;
var tipLabel = state.hasGutter && document.createDocumentFragment();
for (var i = 0; i < anns.length; ++i) {
var ann = anns[i];
var severity = ann.severity;
if (!SEVERITIES.test(severity)) severity = "error";
maxSeverity = getMaxSeverity(maxSeverity, severity);
if (options.formatAnnotation) ann = options.formatAnnotation(ann);
if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));
if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
className: "CodeMirror-lint-span-" + severity,
__annotation: ann
}));
}
if (state.hasGutter)
cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1));
}
if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
}
function onChange(cm) {
var state = cm._lintState;
clearTimeout(state.timeout);
state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
}
function popupSpanTooltip(ann, e) {
var tooltip = showTooltip(e, annotationTooltip(ann));
var target = e.target || e.srcElement;
CodeMirror.on(target, "mouseout", hide);
function hide() {
CodeMirror.off(target, "mouseout", hide);
hideTooltip(tooltip);
}
}
// When the mouseover fires, the cursor might not actually be over
// the character itself yet. These pairs of x,y offsets are used to
// probe a few nearby points when no suitable marked range is found.
var nearby = [0, 0, 0, 5, 0, -5, 5, 0, -5, 0];
function onMouseOver(cm, e) {
if (!/\bCodeMirror-lint-span-/.test((e.target || e.srcElement).className)) return;
for (var i = 0; i < nearby.length; i += 2) {
var spans = cm.findMarksAt(cm.coordsChar({left: e.clientX + nearby[i],
top: e.clientY + nearby[i + 1]}));
for (var j = 0; j < spans.length; ++j) {
var span = spans[j], ann = span.__annotation;
if (ann) return popupSpanTooltip(ann, e);
}
}
}
CodeMirror.defineOption("lintWith", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
clearMarks(cm);
cm.off("change", onChange);
CodeMirror.off(cm.getWrapperElement(), "mouseover", cm._lintState.onMouseOver);
delete cm._lintState;
}
if (val) {
var gutters = cm.getOption("gutters"), hasLintGutter = false;
for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
var state = cm._lintState = new LintState(cm, parseOptions(val), hasLintGutter);
cm.on("change", onChange);
CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
startLinting(cm);
}
});
})();

View File

@@ -0,0 +1,51 @@
(function() {
if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
var loading = {};
function splitCallback(cont, n) {
var countDown = n;
return function() { if (--countDown == 0) cont(); };
}
function ensureDeps(mode, cont) {
var deps = CodeMirror.modes[mode].dependencies;
if (!deps) return cont();
var missing = [];
for (var i = 0; i < deps.length; ++i) {
if (!CodeMirror.modes.hasOwnProperty(deps[i]))
missing.push(deps[i]);
}
if (!missing.length) return cont();
var split = splitCallback(cont, missing.length);
for (var i = 0; i < missing.length; ++i)
CodeMirror.requireMode(missing[i], split);
}
CodeMirror.requireMode = function(mode, cont) {
if (typeof mode != "string") mode = mode.name;
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
var script = document.createElement("script");
script.src = CodeMirror.modeURL.replace(/%N/g, mode);
var others = document.getElementsByTagName("script")[0];
others.parentNode.insertBefore(script, others);
var list = loading[mode] = [cont];
var count = 0, poll = setInterval(function() {
if (++count > 100) return clearInterval(poll);
if (CodeMirror.modes.hasOwnProperty(mode)) {
clearInterval(poll);
loading[mode] = null;
ensureDeps(mode, function() {
for (var i = 0; i < list.length; ++i) list[i]();
});
}
}, 200);
};
CodeMirror.autoLoadMode = function(instance, mode) {
if (!CodeMirror.modes.hasOwnProperty(mode))
CodeMirror.requireMode(mode, function() {
instance.setOption("mode", instance.getOption("mode"));
});
};
}());

View File

@@ -0,0 +1,95 @@
CodeMirror.multiplexingMode = function(outer /*, others */) {
// Others should be {open, close, mode [, delimStyle]} objects
var others = Array.prototype.slice.call(arguments, 1);
var n_others = others.length;
function indexOf(string, pattern, from) {
if (typeof pattern == "string") return string.indexOf(pattern, from);
var m = pattern.exec(from ? string.slice(from) : string);
return m ? m.index + from : -1;
}
return {
startState: function() {
return {
outer: CodeMirror.startState(outer),
innerActive: null,
inner: null
};
},
copyState: function(state) {
return {
outer: CodeMirror.copyState(outer, state.outer),
innerActive: state.innerActive,
inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
};
},
token: function(stream, state) {
if (!state.innerActive) {
var cutOff = Infinity, oldContent = stream.string;
for (var i = 0; i < n_others; ++i) {
var other = others[i];
var found = indexOf(oldContent, other.open, stream.pos);
if (found == stream.pos) {
stream.match(other.open);
state.innerActive = other;
state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
return other.delimStyle;
} else if (found != -1 && found < cutOff) {
cutOff = found;
}
}
if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
var outerToken = outer.token(stream, state.outer);
if (cutOff != Infinity) stream.string = oldContent;
return outerToken;
} else {
var curInner = state.innerActive, oldContent = stream.string;
var found = indexOf(oldContent, curInner.close, stream.pos);
if (found == stream.pos) {
stream.match(curInner.close);
state.innerActive = state.inner = null;
return curInner.delimStyle;
}
if (found > -1) stream.string = oldContent.slice(0, found);
var innerToken = curInner.mode.token(stream, state.inner);
if (found > -1) stream.string = oldContent;
var cur = stream.current(), found = cur.indexOf(curInner.close);
if (found > -1) stream.backUp(cur.length - found);
return innerToken;
}
},
indent: function(state, textAfter) {
var mode = state.innerActive ? state.innerActive.mode : outer;
if (!mode.indent) return CodeMirror.Pass;
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) {
return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
}
};
};

View File

@@ -0,0 +1,59 @@
// Utility function that allows modes to be combined. The mode given
// as the base argument takes care of most of the normal mode
// functionality, but a second (typically simple) mode is used, which
// can override the style of text. Both modes get to parse all of the
// text, but when both assign a non-null style to a piece of code, the
// overlay wins, unless the combine argument was true, in which case
// the styles are combined.
// overlayParser is the old, deprecated name
CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, combine) {
return {
startState: function() {
return {
base: CodeMirror.startState(base),
overlay: CodeMirror.startState(overlay),
basePos: 0, baseCur: null,
overlayPos: 0, overlayCur: null
};
},
copyState: function(state) {
return {
base: CodeMirror.copyState(base, state.base),
overlay: CodeMirror.copyState(overlay, state.overlay),
basePos: state.basePos, baseCur: null,
overlayPos: state.overlayPos, overlayCur: null
};
},
token: function(stream, state) {
if (stream.start == state.basePos) {
state.baseCur = base.token(stream, state.base);
state.basePos = stream.pos;
}
if (stream.start == state.overlayPos) {
stream.pos = stream.start;
state.overlayCur = overlay.token(stream, state.overlay);
state.overlayPos = stream.pos;
}
stream.pos = Math.min(state.basePos, state.overlayPos);
if (stream.eol()) state.basePos = state.overlayPos = 0;
if (state.overlayCur == null) return state.baseCur;
if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur;
else return state.overlayCur;
},
indent: base.indent && function(state, textAfter) {
return base.indent(state.base, textAfter);
},
electricChars: base.electricChars,
innerMode: function(state) { return {state: state.base, mode: base}; },
blankLine: function(state) {
if (base.blankLine) base.blankLine(state.base);
if (overlay.blankLine) overlay.blankLine(state.overlay);
}
};
};

View File

@@ -0,0 +1,29 @@
CodeMirror.colorize = (function() {
var isBlock = /^(p|li|div|h\\d|pre|blockquote|td)$/;
function textContent(node, out) {
if (node.nodeType == 3) return out.push(node.nodeValue);
for (var ch = node.firstChild; ch; ch = ch.nextSibling) {
textContent(ch, out);
if (isBlock.test(node.nodeType)) out.push("\n");
}
}
return function(collection, defaultMode) {
if (!collection) collection = document.body.getElementsByTagName("pre");
for (var i = 0; i < collection.length; ++i) {
var node = collection[i];
var mode = node.getAttribute("data-lang") || defaultMode;
if (!mode) continue;
var text = [];
textContent(node, text);
node.innerHTML = "";
CodeMirror.runMode(text.join(""), mode, node);
node.className += " cm-s-default";
}
};
})();

View File

@@ -0,0 +1,130 @@
/* Just enough of CodeMirror to run runMode under node.js */
window.CodeMirror = {};
function splitLines(string){ return string.split(/\r?\n|\r/); };
function StringStream(string) {
this.pos = this.start = 0;
this.string = string;
}
StringStream.prototype = {
eol: function() {return this.pos >= this.string.length;},
sol: function() {return this.pos == 0;},
peek: function() {return this.string.charAt(this.pos) || null;},
next: function() {
if (this.pos < this.string.length)
return this.string.charAt(this.pos++);
},
eat: function(match) {
var ch = this.string.charAt(this.pos);
if (typeof match == "string") var ok = ch == match;
else var ok = ch && (match.test ? match.test(ch) : match(ch));
if (ok) {++this.pos; return ch;}
},
eatWhile: function(match) {
var start = this.pos;
while (this.eat(match)){}
return this.pos > start;
},
eatSpace: function() {
var start = this.pos;
while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
return this.pos > start;
},
skipToEnd: function() {this.pos = this.string.length;},
skipTo: function(ch) {
var found = this.string.indexOf(ch, this.pos);
if (found > -1) {this.pos = found; return true;}
},
backUp: function(n) {this.pos -= n;},
column: function() {return this.start;},
indentation: function() {return 0;},
match: function(pattern, consume, caseInsensitive) {
if (typeof pattern == "string") {
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
if (consume !== false) this.pos += pattern.length;
return true;
}
} else {
var match = this.string.slice(this.pos).match(pattern);
if (match && consume !== false) this.pos += match[0].length;
return match;
}
},
current: function(){return this.string.slice(this.start, this.pos);}
};
CodeMirror.StringStream = StringStream;
CodeMirror.startState = function (mode, a1, a2) {
return mode.startState ? mode.startState(a1, a2) : true;
};
var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
CodeMirror.defineMode = function (name, mode) { modes[name] = mode; };
CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };
CodeMirror.getMode = function (options, spec) {
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
spec = mimeModes[spec];
if (typeof spec == "string")
var mname = spec, config = {};
else if (spec != null)
var mname = spec.name, config = spec;
var mfactory = modes[mname];
if (!mfactory) throw new Error("Unknown mode: " + spec);
return mfactory(options, config || {});
};
CodeMirror.runMode = function (string, modespec, callback, options) {
var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
if (callback.nodeType == 1) {
var tabSize = (options && options.tabSize) || 4;
var node = callback, col = 0;
node.innerHTML = "";
callback = function (text, style) {
if (text == "\n") {
node.appendChild(document.createElement("br"));
col = 0;
return;
}
var content = "";
// replace tabs
for (var pos = 0; ;) {
var idx = text.indexOf("\t", pos);
if (idx == -1) {
content += text.slice(pos);
col += text.length - pos;
break;
} else {
col += idx - pos;
content += text.slice(pos, idx);
var size = tabSize - col % tabSize;
col += size;
for (var i = 0; i < size; ++i) content += " ";
pos = idx + 1;
}
}
if (style) {
var sp = node.appendChild(document.createElement("span"));
sp.className = "cm-" + style.replace(/ +/g, " cm-");
sp.appendChild(document.createTextNode(content));
} else {
node.appendChild(document.createTextNode(content));
}
};
}
var lines = splitLines(string), state = CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n");
var stream = new CodeMirror.StringStream(lines[i]);
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start);
stream.start = stream.pos;
}
}
};

View File

@@ -0,0 +1,52 @@
CodeMirror.runMode = function(string, modespec, callback, options) {
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
if (callback.nodeType == 1) {
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
var node = callback, col = 0;
node.innerHTML = "";
callback = function(text, style) {
if (text == "\n") {
node.appendChild(document.createElement("br"));
col = 0;
return;
}
var content = "";
// replace tabs
for (var pos = 0;;) {
var idx = text.indexOf("\t", pos);
if (idx == -1) {
content += text.slice(pos);
col += text.length - pos;
break;
} else {
col += idx - pos;
content += text.slice(pos, idx);
var size = tabSize - col % tabSize;
col += size;
for (var i = 0; i < size; ++i) content += " ";
pos = idx + 1;
}
}
if (style) {
var sp = node.appendChild(document.createElement("span"));
sp.className = "cm-" + style.replace(/ +/g, " cm-");
sp.appendChild(document.createTextNode(content));
} else {
node.appendChild(document.createTextNode(content));
}
};
}
var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n");
var stream = new CodeMirror.StringStream(lines[i]);
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start);
stream.start = stream.pos;
}
}
};

View File

@@ -0,0 +1,89 @@
/* Just enough of CodeMirror to run runMode under node.js */
function splitLines(string){ return string.split(/\r?\n|\r/); };
function StringStream(string) {
this.pos = this.start = 0;
this.string = string;
}
StringStream.prototype = {
eol: function() {return this.pos >= this.string.length;},
sol: function() {return this.pos == 0;},
peek: function() {return this.string.charAt(this.pos) || null;},
next: function() {
if (this.pos < this.string.length)
return this.string.charAt(this.pos++);
},
eat: function(match) {
var ch = this.string.charAt(this.pos);
if (typeof match == "string") var ok = ch == match;
else var ok = ch && (match.test ? match.test(ch) : match(ch));
if (ok) {++this.pos; return ch;}
},
eatWhile: function(match) {
var start = this.pos;
while (this.eat(match)){}
return this.pos > start;
},
eatSpace: function() {
var start = this.pos;
while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
return this.pos > start;
},
skipToEnd: function() {this.pos = this.string.length;},
skipTo: function(ch) {
var found = this.string.indexOf(ch, this.pos);
if (found > -1) {this.pos = found; return true;}
},
backUp: function(n) {this.pos -= n;},
column: function() {return this.start;},
indentation: function() {return 0;},
match: function(pattern, consume, caseInsensitive) {
if (typeof pattern == "string") {
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
if (consume !== false) this.pos += pattern.length;
return true;
}
} else {
var match = this.string.slice(this.pos).match(pattern);
if (match && consume !== false) this.pos += match[0].length;
return match;
}
},
current: function(){return this.string.slice(this.start, this.pos);}
};
exports.StringStream = StringStream;
exports.startState = function(mode, a1, a2) {
return mode.startState ? mode.startState(a1, a2) : true;
};
var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
exports.defineMode = function(name, mode) { modes[name] = mode; };
exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
exports.getMode = function(options, spec) {
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec))
spec = mimeModes[spec];
if (typeof spec == "string")
var mname = spec, config = {};
else if (spec != null)
var mname = spec.name, config = spec;
var mfactory = modes[mname];
if (!mfactory) throw new Error("Unknown mode: " + spec);
return mfactory(options, config || {});
};
exports.runMode = function(string, modespec, callback) {
var mode = exports.getMode({indentUnit: 2}, modespec);
var lines = splitLines(string), state = exports.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n");
var stream = new exports.StringStream(lines[i]);
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start);
stream.start = stream.pos;
}
}
};

View File

@@ -0,0 +1,60 @@
// Highlighting text that matches the selection
//
// Defines an option highlightSelectionMatches, which, when enabled,
// will style strings that match the selection throughout the
// document.
//
// The option can be set to true to simply enable it, or to a
// {minChars, style} object to explicitly configure it. minChars is
// the minimum amount of characters that should be selected for the
// behavior to occur, and style is the token style to apply to the
// matches. This will be prefixed by "cm-" to create an actual CSS
// class name.
(function() {
var DEFAULT_MIN_CHARS = 2;
var DEFAULT_TOKEN_STYLE = "matchhighlight";
function State(options) {
this.minChars = typeof options == "object" && options.minChars || DEFAULT_MIN_CHARS;
this.style = typeof options == "object" && options.style || DEFAULT_TOKEN_STYLE;
this.overlay = null;
}
CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) {
var prev = old && old != CodeMirror.Init;
if (val && !prev) {
cm._matchHighlightState = new State(val);
cm.on("cursorActivity", highlightMatches);
} else if (!val && prev) {
var over = cm._matchHighlightState.overlay;
if (over) cm.removeOverlay(over);
cm._matchHighlightState = null;
cm.off("cursorActivity", highlightMatches);
}
});
function highlightMatches(cm) {
cm.operation(function() {
var state = cm._matchHighlightState;
if (state.overlay) {
cm.removeOverlay(state.overlay);
state.overlay = null;
}
if (!cm.somethingSelected()) return;
var selection = cm.getSelection().replace(/^\s+|\s+$/g, "");
if (selection.length < state.minChars) return;
cm.addOverlay(state.overlay = makeOverlay(selection, state.style));
});
}
function makeOverlay(query, style) {
return {token: function(stream) {
if (stream.match(query)) return style;
stream.next();
stream.skipTo(query.charAt(0)) || stream.skipToEnd();
}};
}
})();

View File

@@ -0,0 +1,131 @@
// Define search commands. Depends on dialog.js or another
// implementation of the openDialog method.
// Replace works a little oddly -- it will do the replace on the next
// Ctrl-G (or whatever is bound to findNext) press. You prevent a
// replace by making sure the match is no longer selected when hitting
// Ctrl-G.
(function() {
function searchOverlay(query) {
if (typeof query == "string") return {token: function(stream) {
if (stream.match(query)) return "searching";
stream.next();
stream.skipTo(query.charAt(0)) || stream.skipToEnd();
}};
return {token: function(stream) {
if (stream.match(query)) return "searching";
while (!stream.eol()) {
stream.next();
if (stream.match(query, false)) break;
}
}};
}
function SearchState() {
this.posFrom = this.posTo = this.query = null;
this.overlay = null;
}
function getSearchState(cm) {
return cm._searchState || (cm._searchState = new SearchState());
}
function getSearchCursor(cm, query, pos) {
// Heuristic: if the query string is all lowercase, do a case insensitive search.
return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase());
}
function dialog(cm, text, shortText, f) {
if (cm.openDialog) cm.openDialog(text, f);
else f(prompt(shortText, ""));
}
function confirmDialog(cm, text, shortText, fs) {
if (cm.openConfirm) cm.openConfirm(text, fs);
else if (confirm(shortText)) fs[0]();
}
function parseQuery(query) {
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query;
}
var queryDialog =
'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
function doSearch(cm, rev) {
var state = getSearchState(cm);
if (state.query) return findNext(cm, rev);
dialog(cm, queryDialog, "Search for:", function(query) {
cm.operation(function() {
if (!query || state.query) return;
state.query = parseQuery(query);
cm.removeOverlay(state.overlay);
state.overlay = searchOverlay(query);
cm.addOverlay(state.overlay);
state.posFrom = state.posTo = cm.getCursor();
findNext(cm, rev);
});
});
}
function findNext(cm, rev) {cm.operation(function() {
var state = getSearchState(cm);
var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
if (!cursor.find(rev)) {
cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
if (!cursor.find(rev)) return;
}
cm.setSelection(cursor.from(), cursor.to());
state.posFrom = cursor.from(); state.posTo = cursor.to();
});}
function clearSearch(cm) {cm.operation(function() {
var state = getSearchState(cm);
if (!state.query) return;
state.query = null;
cm.removeOverlay(state.overlay);
});}
var replaceQueryDialog =
'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
function replace(cm, all) {
dialog(cm, replaceQueryDialog, "Replace:", function(query) {
if (!query) return;
query = parseQuery(query);
dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
if (all) {
cm.operation(function() {
for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
if (typeof query != "string") {
var match = cm.getRange(cursor.from(), cursor.to()).match(query);
cursor.replace(text.replace(/\$(\d)/, function(_, i) {return match[i];}));
} else cursor.replace(text);
}
});
} else {
clearSearch(cm);
var cursor = getSearchCursor(cm, query, cm.getCursor());
var advance = function() {
var start = cursor.from(), match;
if (!(match = cursor.findNext())) {
cursor = getSearchCursor(cm, query);
if (!(match = cursor.findNext()) ||
(start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
}
cm.setSelection(cursor.from(), cursor.to());
confirmDialog(cm, doReplaceConfirm, "Replace?",
[function() {doReplace(match);}, advance]);
};
var doReplace = function(match) {
cursor.replace(typeof query == "string" ? text :
text.replace(/\$(\d)/, function(_, i) {return match[i];}));
advance();
};
advance();
}
});
});
}
CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
CodeMirror.commands.findNext = doSearch;
CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
CodeMirror.commands.clearSearch = clearSearch;
CodeMirror.commands.replace = replace;
CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
})();

View File

@@ -0,0 +1,130 @@
(function(){
var Pos = CodeMirror.Pos;
function SearchCursor(cm, query, pos, caseFold) {
this.atOccurrence = false; this.cm = cm;
if (caseFold == null && typeof query == "string") caseFold = false;
pos = pos ? cm.clipPos(pos) : Pos(0, 0);
this.pos = {from: pos, to: pos};
// The matches method is filled in based on the type of query.
// It takes a position and a direction, and returns an object
// describing the next occurrence of the query, or null if no
// more matches were found.
if (typeof query != "string") { // Regexp match
if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g");
this.matches = function(reverse, pos) {
if (reverse) {
query.lastIndex = 0;
var line = cm.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start;
for (;;) {
query.lastIndex = cutOff;
var newMatch = query.exec(line);
if (!newMatch) break;
match = newMatch;
start = match.index;
cutOff = match.index + 1;
}
} else {
query.lastIndex = pos.ch;
var line = cm.getLine(pos.line), match = query.exec(line),
start = match && match.index;
}
if (match && match[0])
return {from: Pos(pos.line, start),
to: Pos(pos.line, start + match[0].length),
match: match};
};
} else { // String query
if (caseFold) query = query.toLowerCase();
var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};
var target = query.split("\n");
// Different methods for single-line and multi-line queries
if (target.length == 1) {
if (!query.length) {
// Empty string would match anything and never progress, so
// we define it to match nothing instead.
this.matches = function() {};
} else {
this.matches = function(reverse, pos) {
var line = fold(cm.getLine(pos.line)), len = query.length, match;
if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)
: (match = line.indexOf(query, pos.ch)) != -1)
return {from: Pos(pos.line, match),
to: Pos(pos.line, match + len)};
};
}
} else {
this.matches = function(reverse, pos) {
var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln));
var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));
if (reverse ? offsetA >= pos.ch || offsetA != match.length
: offsetA <= pos.ch || offsetA != line.length - match.length)
return;
for (;;) {
if (reverse ? !ln : ln == cm.lineCount() - 1) return;
line = fold(cm.getLine(ln += reverse ? -1 : 1));
match = target[reverse ? --idx : ++idx];
if (idx > 0 && idx < target.length - 1) {
if (line != match) return;
else continue;
}
var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);
if (reverse ? offsetB != line.length - match.length : offsetB != match.length)
return;
var start = Pos(pos.line, offsetA), end = Pos(ln, offsetB);
return {from: reverse ? end : start, to: reverse ? start : end};
}
};
}
}
}
SearchCursor.prototype = {
findNext: function() {return this.find(false);},
findPrevious: function() {return this.find(true);},
find: function(reverse) {
var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to);
function savePosAndFail(line) {
var pos = Pos(line, 0);
self.pos = {from: pos, to: pos};
self.atOccurrence = false;
return false;
}
for (;;) {
if (this.pos = this.matches(reverse, pos)) {
if (!this.pos.from || !this.pos.to) { console.log(this.matches, this.pos); }
this.atOccurrence = true;
return this.pos.match || true;
}
if (reverse) {
if (!pos.line) return savePosAndFail(0);
pos = Pos(pos.line-1, this.cm.getLine(pos.line-1).length);
}
else {
var maxLine = this.cm.lineCount();
if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
pos = Pos(pos.line + 1, 0);
}
}
},
from: function() {if (this.atOccurrence) return this.pos.from;},
to: function() {if (this.atOccurrence) return this.pos.to;},
replace: function(newText) {
if (!this.atOccurrence) return;
var lines = CodeMirror.splitLines(newText);
this.cm.replaceRange(lines, this.pos.from, this.pos.to);
this.pos.to = Pos(this.pos.from.line + lines.length - 1,
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
}
};
CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
return new SearchCursor(this, query, pos, caseFold);
});
})();

View File

@@ -0,0 +1,39 @@
// Because sometimes you need to style the cursor's line.
//
// Adds an option 'styleActiveLine' which, when enabled, gives the
// active line's wrapping <div> the CSS class "CodeMirror-activeline",
// and gives its background <div> the class "CodeMirror-activeline-background".
(function() {
"use strict";
var WRAP_CLASS = "CodeMirror-activeline";
var BACK_CLASS = "CodeMirror-activeline-background";
CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
var prev = old && old != CodeMirror.Init;
if (val && !prev) {
updateActiveLine(cm);
cm.on("cursorActivity", updateActiveLine);
} else if (!val && prev) {
cm.off("cursorActivity", updateActiveLine);
clearActiveLine(cm);
delete cm._activeLine;
}
});
function clearActiveLine(cm) {
if ("_activeLine" in cm) {
cm.removeLineClass(cm._activeLine, "wrap", WRAP_CLASS);
cm.removeLineClass(cm._activeLine, "background", BACK_CLASS);
}
}
function updateActiveLine(cm) {
var line = cm.getLineHandle(cm.getCursor().line);
if (cm._activeLine == line) return;
clearActiveLine(cm);
cm.addLineClass(line, "wrap", WRAP_CLASS);
cm.addLineClass(line, "background", BACK_CLASS);
cm._activeLine = line;
}
})();

View File

@@ -0,0 +1,34 @@
// Because sometimes you need to mark the selected *text*.
//
// Adds an option 'styleSelectedText' which, when enabled, gives
// selected text the CSS class "CodeMirror-selectedtext".
(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);
} else if (!val && prev) {
cm.off("cursorActivity", updateSelectedText);
clearSelectedText(cm);
delete cm._selectionMark;
}
});
function clearSelectedText(cm) {
if (cm._selectionMark) cm._selectionMark.clear();
}
function updateSelectedText(cm) {
clearSelectedText(cm);
if (cm.somethingSelected())
cm._selectionMark = cm.markText(cm.getCursor("start"), cm.getCursor("end"),
{className: "CodeMirror-selectedtext"});
else
cm._selectionMark = null;
}
})();

View File

@@ -22,21 +22,19 @@
<h2>CodeMirror: Autocomplete demo</h2>
<form><textarea id="code" name="code">
<?php
function getData($data) {
$tre = $data . " fff ";
$tre = $data . " fffoX ";
return $tre;
}
$sa =
$sa = "";
PMFAddInputDocument(
$list = array("a" => 1, "b" => 2, "c" => 4 );
?>
</textarea></form>
<button onclick="gettext()">get Text</button>
<button onclick="insertText()">insert</button>
<button onclick="mark()">replace marked</button>
<p>Press <strong>ctrl-space</strong> to activate autocompletion. See
the code (<a href="../addon/hint/show-hint.js">here</a>
and <a href="../addon/hint/php-hint.js">here</a>) to figure out
@@ -46,14 +44,38 @@ how it works.</p>
CodeMirror.commands.autocomplete = function(cm) {
CodeMirror.showHint(cm, CodeMirror.phpHint);
}
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
matchBrackets: true,
mode: "application/x-httpd-php",
PMEnabled: true,
indentUnit: 2,
indentWithTabs: true,
indentWithTabs: false,
extraKeys: {"Ctrl-Space": "autocomplete"}
});
editor.save();
//editor.toTextArea(); //reset to the textArea
alert(editor.getTextArea().value);
editor.focus();
CodeMirror.commands.selectAll(editor);
function gettext() {
var cur = editor.getCursor();
var text1 = editor.getLine(cur.line);
alert("text: ''" + text1 + "''");
}
function insertText() {
var cur = editor.getCursor();
editor.replaceRange("******", cur);
}
function mark() {
var from = editor.getCursor();
var to ;
editor.replaceSelection("$$$$$$$");
}
</script>
</body>
</html>

View File

@@ -63,6 +63,11 @@
state.curState = state.php;
return "meta";
}
if( config.PMEnabled == true) {
state.curMode = phpMode;
state.curState = state.php;
return "meta";
}
if (state.pending == '"') {
while (!stream.eol() && stream.next() != '"') {}
var style = "string";