first commit
This commit is contained in:
245
codemirror/lib/codemirror.css
vendored
Normal file
245
codemirror/lib/codemirror.css
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
/* BASICS */
|
||||
|
||||
.CodeMirror {
|
||||
/* Set height, width, borders, and global font properties here */
|
||||
font-family: monospace;
|
||||
height: 300px;
|
||||
}
|
||||
.CodeMirror-scroll {
|
||||
/* Set scrolling behaviour here */
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* PADDING */
|
||||
|
||||
.CodeMirror-lines {
|
||||
padding: 4px 0; /* Vertical padding around content */
|
||||
}
|
||||
.CodeMirror pre {
|
||||
padding: 0 4px; /* Horizontal padding of content */
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler {
|
||||
background-color: white; /* The little square between H and V scrollbars */
|
||||
}
|
||||
|
||||
/* GUTTER */
|
||||
|
||||
.CodeMirror-gutters {
|
||||
border-right: 1px solid #ddd;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
.CodeMirror-linenumbers {}
|
||||
.CodeMirror-linenumber {
|
||||
padding: 0 3px 0 5px;
|
||||
min-width: 20px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* CURSOR */
|
||||
|
||||
.CodeMirror pre.CodeMirror-cursor {
|
||||
border-left: 1px solid black;
|
||||
}
|
||||
/* Shown when moving in bi-directional text */
|
||||
.CodeMirror pre.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
.cm-keymap-fat-cursor pre.CodeMirror-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
background: rgba(0, 200, 0, .4);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
|
||||
}
|
||||
/* Kludge to turn off filter in ie9+, which also accepts rgba */
|
||||
.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
/* Can style cursor different in overwrite (non-insert) mode */
|
||||
.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}
|
||||
|
||||
/* DEFAULT THEME */
|
||||
|
||||
.cm-s-default .cm-keyword {color: #708;}
|
||||
.cm-s-default .cm-atom {color: #219;}
|
||||
.cm-s-default .cm-number {color: #164;}
|
||||
.cm-s-default .cm-def {color: #00f;}
|
||||
.cm-s-default .cm-variable {color: black;}
|
||||
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||
.cm-s-default .cm-variable-3 {color: #085;}
|
||||
.cm-s-default .cm-property {color: black;}
|
||||
.cm-s-default .cm-operator {color: black;}
|
||||
.cm-s-default .cm-comment {color: #a50;}
|
||||
.cm-s-default .cm-string {color: #a11;}
|
||||
.cm-s-default .cm-string-2 {color: #f50;}
|
||||
.cm-s-default .cm-meta {color: #555;}
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-s-default .cm-qualifier {color: #555;}
|
||||
.cm-s-default .cm-builtin {color: #30a;}
|
||||
.cm-s-default .cm-bracket {color: #997;}
|
||||
.cm-s-default .cm-tag {color: #170;}
|
||||
.cm-s-default .cm-attribute {color: #00c;}
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-s-default .cm-hr {color: #999;}
|
||||
.cm-s-default .cm-link {color: #00c;}
|
||||
|
||||
.cm-negative {color: #d44;}
|
||||
.cm-positive {color: #292;}
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-emstrong {font-style: italic; font-weight: bold;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
|
||||
/* STOP */
|
||||
|
||||
/* The rest of this file contains styles related to the mechanics of
|
||||
the editor. You probably shouldn't touch them. */
|
||||
|
||||
.CodeMirror {
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||
/* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
|
||||
margin-bottom: -30px; margin-right: -30px;
|
||||
padding-bottom: 30px; padding-right: 30px;
|
||||
height: 100%;
|
||||
outline: none; /* Prevent dragging from highlighting the element */
|
||||
position: relative;
|
||||
}
|
||||
.CodeMirror-sizer {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||
before actuall scrolling happens, thus preventing shaking and
|
||||
flickering artifacts. */
|
||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
display: none;
|
||||
}
|
||||
.CodeMirror-vscrollbar {
|
||||
right: 0; top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.CodeMirror-hscrollbar {
|
||||
bottom: 0; left: 0;
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.CodeMirror-scrollbar-filler {
|
||||
right: 0; bottom: 0;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
position: absolute; left: 0; top: 0;
|
||||
height: 100%;
|
||||
z-index: 3;
|
||||
}
|
||||
.CodeMirror-gutter {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
/* Hack to make IE7 behave */
|
||||
*zoom:1;
|
||||
*display:inline;
|
||||
}
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.CodeMirror-lines {
|
||||
cursor: text;
|
||||
}
|
||||
.CodeMirror pre {
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
-moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
|
||||
border-width: 0;
|
||||
background: transparent;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin: 0;
|
||||
white-space: pre;
|
||||
word-wrap: normal;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
.CodeMirror-wrap pre {
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
word-break: normal;
|
||||
}
|
||||
.CodeMirror-linebackground {
|
||||
position: absolute;
|
||||
left: 0; right: 0; top: 0; bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-linewidget {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.CodeMirror-wrap .CodeMirror-scroll {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-measure {
|
||||
position: absolute;
|
||||
width: 100%; height: 0px;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
.CodeMirror-measure pre { position: static; }
|
||||
|
||||
.CodeMirror pre.CodeMirror-cursor {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
}
|
||||
.CodeMirror-focused pre.CodeMirror-cursor {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-selected { background: #d9d9d9; }
|
||||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||
|
||||
.cm-searching {
|
||||
background: #ffa;
|
||||
background: rgba(255, 255, 0, .4);
|
||||
}
|
||||
|
||||
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
|
||||
.CodeMirror span { *vertical-align: text-bottom; }
|
||||
.CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
|
||||
.cm-tab {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);
|
||||
background-position: right;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
@media print {
|
||||
/* Hide the cursor when printing */
|
||||
.CodeMirror pre.CodeMirror-cursor {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
4646
codemirror/lib/codemirror.js
vendored
Normal file
4646
codemirror/lib/codemirror.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
85
codemirror/lib/util/closetag.js
vendored
Normal file
85
codemirror/lib/util/closetag.js
vendored
Normal 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) { autoCloseTag(cm, '/'); };
|
||||
if (typeof val != "object" || val.whenOpening)
|
||||
map["'>'"] = function(cm) { autoCloseTag(cm, '>'); };
|
||||
cm.addKeyMap(map);
|
||||
} else if (!val && (old != CodeMirror.Init && old)) {
|
||||
cm.removeKeyMap("autoCloseTags");
|
||||
}
|
||||
});
|
||||
|
||||
var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
|
||||
"source", "track", "wbr"];
|
||||
var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
|
||||
"h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
|
||||
|
||||
function autoCloseTag(cm, ch) {
|
||||
var pos = cm.getCursor(), tok = cm.getTokenAt(pos);
|
||||
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
|
||||
if (inner.mode.name != "xml") throw CodeMirror.Pass;
|
||||
|
||||
var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";
|
||||
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
|
||||
var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
|
||||
|
||||
if (ch == ">" && state.tagName) {
|
||||
var tagName = state.tagName;
|
||||
if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
|
||||
var lowerTagName = tagName.toLowerCase();
|
||||
// Don't process the '>' at the end of an end-tag or self-closing tag
|
||||
if (tok.type == "tag" && state.type == "closeTag" ||
|
||||
/\/\s*$/.test(tok.string) ||
|
||||
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1)
|
||||
throw CodeMirror.Pass;
|
||||
|
||||
var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1;
|
||||
cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "</" + tagName + ">",
|
||||
doIndent ? {line: pos.line + 1, ch: 0} : {line: pos.line, ch: pos.ch + 1});
|
||||
if (doIndent) {
|
||||
cm.indentLine(pos.line + 1);
|
||||
cm.indentLine(pos.line + 2);
|
||||
}
|
||||
return;
|
||||
} else if (ch == "/" && tok.type == "tag" && tok.string == "<") {
|
||||
var tagName = state.context && state.context.tagName;
|
||||
if (tagName) cm.replaceSelection("/" + tagName + ">", "end");
|
||||
return;
|
||||
}
|
||||
throw CodeMirror.Pass;
|
||||
}
|
||||
|
||||
function indexOf(collection, elt) {
|
||||
if (collection.indexOf) return collection.indexOf(elt);
|
||||
for (var i = 0, e = collection.length; i < e; ++i)
|
||||
if (collection[i] == elt) return i;
|
||||
return -1;
|
||||
}
|
||||
})();
|
||||
29
codemirror/lib/util/colorize.js
vendored
Normal file
29
codemirror/lib/util/colorize.js
vendored
Normal 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";
|
||||
}
|
||||
};
|
||||
})();
|
||||
36
codemirror/lib/util/continuecomment.js
vendored
Normal file
36
codemirror/lib/util/continuecomment.js
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
(function() {
|
||||
var modes = ["clike", "css", "javascript"];
|
||||
for (var i = 0; i < modes.length; ++i)
|
||||
CodeMirror.extendMode(modes[i], {blockCommentStart: "/*",
|
||||
blockCommentEnd: "*/",
|
||||
blockCommentContinue: " * "});
|
||||
|
||||
CodeMirror.commands.newlineAndIndentContinueComment = function(cm) {
|
||||
var pos = cm.getCursor(), token = cm.getTokenAt(pos);
|
||||
var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode;
|
||||
var space;
|
||||
|
||||
if (token.type == "comment" && mode.blockCommentStart) {
|
||||
var end = token.string.indexOf(mode.blockCommentEnd);
|
||||
var full = cm.getRange({line: pos.line, ch: 0}, {line: pos.line, ch: token.end}), found;
|
||||
if (end != -1 && end == token.string.length - mode.blockCommentEnd.length) {
|
||||
// Comment ended, don't continue it
|
||||
} else if (token.string.indexOf(mode.blockCommentStart) == 0) {
|
||||
space = full.slice(0, token.start);
|
||||
if (!/^\s*$/.test(space)) {
|
||||
space = "";
|
||||
for (var i = 0; i < token.start; ++i) space += " ";
|
||||
}
|
||||
} else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
|
||||
found + mode.blockCommentContinue.length > token.start &&
|
||||
/^\s*$/.test(full.slice(0, found))) {
|
||||
space = full.slice(0, found);
|
||||
}
|
||||
}
|
||||
|
||||
if (space != null)
|
||||
cm.replaceSelection("\n" + space + mode.blockCommentContinue, "end");
|
||||
else
|
||||
cm.execCommand("newlineAndIndent");
|
||||
};
|
||||
})();
|
||||
28
codemirror/lib/util/continuelist.js
vendored
Normal file
28
codemirror/lib/util/continuelist.js
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
(function() {
|
||||
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
|
||||
var pos = cm.getCursor(), token = cm.getTokenAt(pos);
|
||||
var space;
|
||||
if (token.className == "string") {
|
||||
var full = cm.getRange({line: pos.line, ch: 0}, {line: pos.line, ch: token.end});
|
||||
var listStart = /\*|\d+\./, listContinue;
|
||||
if (token.string.search(listStart) == 0) {
|
||||
var reg = /^[\W]*(\d+)\./g;
|
||||
var matches = reg.exec(full);
|
||||
if(matches)
|
||||
listContinue = (parseInt(matches[1]) + 1) + ". ";
|
||||
else
|
||||
listContinue = "* ";
|
||||
space = full.slice(0, token.start);
|
||||
if (!/^\s*$/.test(space)) {
|
||||
space = "";
|
||||
for (var i = 0; i < token.start; ++i) space += " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (space != null)
|
||||
cm.replaceSelection("\n" + space + listContinue, "end");
|
||||
else
|
||||
cm.execCommand("newlineAndIndent");
|
||||
};
|
||||
})();
|
||||
32
codemirror/lib/util/dialog.css
vendored
Normal file
32
codemirror/lib/util/dialog.css
vendored
Normal 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%;
|
||||
}
|
||||
76
codemirror/lib/util/dialog.js
vendored
Normal file
76
codemirror/lib/util/dialog.js
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
// 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 (e.keyCode == 13 || e.keyCode == 27) {
|
||||
CodeMirror.e_stop(e);
|
||||
close();
|
||||
me.focus();
|
||||
if (e.keyCode == 13) callback(inp.value);
|
||||
}
|
||||
});
|
||||
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; });
|
||||
}
|
||||
});
|
||||
})();
|
||||
182
codemirror/lib/util/foldcode.js
vendored
Normal file
182
codemirror/lib/util/foldcode.js
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
// the tagRangeFinder function is
|
||||
// Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
|
||||
// released under the MIT license (../../LICENSE) like the rest of CodeMirror
|
||||
CodeMirror.tagRangeFinder = function(cm, start) {
|
||||
var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
|
||||
var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
|
||||
var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");
|
||||
|
||||
var lineText = cm.getLine(start.line);
|
||||
var found = false;
|
||||
var tag = null;
|
||||
var pos = start.ch;
|
||||
while (!found) {
|
||||
pos = lineText.indexOf("<", pos);
|
||||
if (-1 == pos) // no tag on line
|
||||
return;
|
||||
if (pos + 1 < lineText.length && lineText[pos + 1] == "/") { // closing tag
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
// ok we seem to have a start tag
|
||||
if (!lineText.substr(pos + 1).match(xmlNAMERegExp)) { // not a tag name...
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
var gtPos = lineText.indexOf(">", pos + 1);
|
||||
if (-1 == gtPos) { // end of start tag not in line
|
||||
var l = start.line + 1;
|
||||
var foundGt = false;
|
||||
var lastLine = cm.lineCount();
|
||||
while (l < lastLine && !foundGt) {
|
||||
var lt = cm.getLine(l);
|
||||
gtPos = lt.indexOf(">");
|
||||
if (-1 != gtPos) { // found a >
|
||||
foundGt = true;
|
||||
var slash = lt.lastIndexOf("/", gtPos);
|
||||
if (-1 != slash && slash < gtPos) {
|
||||
var str = lineText.substr(slash, gtPos - slash + 1);
|
||||
if (!str.match( /\/\s*\>/ )) // yep, that's the end of empty tag
|
||||
return;
|
||||
}
|
||||
}
|
||||
l++;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
else {
|
||||
var slashPos = lineText.lastIndexOf("/", gtPos);
|
||||
if (-1 == slashPos) { // cannot be empty tag
|
||||
found = true;
|
||||
// don't continue
|
||||
}
|
||||
else { // empty tag?
|
||||
// check if really empty tag
|
||||
var str = lineText.substr(slashPos, gtPos - slashPos + 1);
|
||||
if (!str.match( /\/\s*\>/ )) { // finally not empty
|
||||
found = true;
|
||||
// don't continue
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
var subLine = lineText.substr(pos + 1);
|
||||
tag = subLine.match(xmlNAMERegExp);
|
||||
if (tag) {
|
||||
// we have an element name, wooohooo !
|
||||
tag = tag[0];
|
||||
// do we have the close tag on same line ???
|
||||
if (-1 != lineText.indexOf("</" + tag + ">", pos)) // yep
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
// we don't, so we have a candidate...
|
||||
}
|
||||
else
|
||||
found = false;
|
||||
}
|
||||
if (!found)
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\\s)|(\\<" + tag + "$)";
|
||||
var startTagRegExp = new RegExp(startTag);
|
||||
var endTag = "</" + tag + ">";
|
||||
var depth = 1;
|
||||
var l = start.line + 1;
|
||||
var lastLine = cm.lineCount();
|
||||
while (l < lastLine) {
|
||||
lineText = cm.getLine(l);
|
||||
var match = lineText.match(startTagRegExp);
|
||||
if (match) {
|
||||
for (var i = 0; i < match.length; i++) {
|
||||
if (match[i] == endTag)
|
||||
depth--;
|
||||
else
|
||||
depth++;
|
||||
if (!depth) return {from: {line: start.line, ch: gtPos + 1},
|
||||
to: {line: l, ch: match.index}};
|
||||
}
|
||||
}
|
||||
l++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
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({line: line, ch: found}).type;
|
||||
if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
|
||||
at = found - 1;
|
||||
}
|
||||
if (startChar == null || lineText.lastIndexOf("}") > startChar) return;
|
||||
var count = 1, lastLine = cm.lineCount(), end, 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({line: i, ch: 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: {line: line, ch: startChar + 1},
|
||||
to: {line: end, ch: endCh}};
|
||||
};
|
||||
|
||||
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)
|
||||
return {from: {line: start.line, ch: firstLine.length},
|
||||
to: {line: i, ch: curLine.length}};
|
||||
}
|
||||
};
|
||||
|
||||
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 = {line: pos, ch: 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
|
||||
});
|
||||
};
|
||||
};
|
||||
108
codemirror/lib/util/formatting.js
vendored
Normal file
108
codemirror/lib/util/formatting.js
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
(function() {
|
||||
|
||||
CodeMirror.extendMode("css", {
|
||||
commentStart: "/*",
|
||||
commentEnd: "*/",
|
||||
newlineAfterToken: function(_type, content) {
|
||||
return /^[;{}]$/.test(content);
|
||||
}
|
||||
});
|
||||
|
||||
CodeMirror.extendMode("javascript", {
|
||||
commentStart: "/*",
|
||||
commentEnd: "*/",
|
||||
// FIXME semicolons inside of for
|
||||
newlineAfterToken: function(_type, content, textAfter, state) {
|
||||
if (this.jsonMode) {
|
||||
return /^[\[,{]$/.test(content) || /^}/.test(textAfter);
|
||||
} else {
|
||||
if (content == ";" && state.lexical && state.lexical.type == ")") return false;
|
||||
return /^[;{}]$/.test(content) && !/^;/.test(textAfter);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
CodeMirror.extendMode("xml", {
|
||||
commentStart: "<!--",
|
||||
commentEnd: "-->",
|
||||
newlineAfterToken: function(type, content, textAfter) {
|
||||
return type == "tag" && />$/.test(content) || /^</.test(textAfter);
|
||||
}
|
||||
});
|
||||
|
||||
// Comment/uncomment the specified range
|
||||
CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
|
||||
var cm = this, curMode = CodeMirror.innerMode(cm.getMode(), cm.getTokenAt(from).state).mode;
|
||||
cm.operation(function() {
|
||||
if (isComment) { // Comment range
|
||||
cm.replaceRange(curMode.commentEnd, to);
|
||||
cm.replaceRange(curMode.commentStart, from);
|
||||
if (from.line == to.line && from.ch == to.ch) // An empty comment inserted - put cursor inside
|
||||
cm.setCursor(from.line, from.ch + curMode.commentStart.length);
|
||||
} else { // Uncomment range
|
||||
var selText = cm.getRange(from, to);
|
||||
var startIndex = selText.indexOf(curMode.commentStart);
|
||||
var endIndex = selText.lastIndexOf(curMode.commentEnd);
|
||||
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
|
||||
// Take string till comment start
|
||||
selText = selText.substr(0, startIndex)
|
||||
// From comment start till comment end
|
||||
+ selText.substring(startIndex + curMode.commentStart.length, endIndex)
|
||||
// From comment end till string end
|
||||
+ selText.substr(endIndex + curMode.commentEnd.length);
|
||||
}
|
||||
cm.replaceRange(selText, from, to);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Applies automatic mode-aware indentation to the specified range
|
||||
CodeMirror.defineExtension("autoIndentRange", function (from, to) {
|
||||
var cmInstance = this;
|
||||
this.operation(function () {
|
||||
for (var i = from.line; i <= to.line; i++) {
|
||||
cmInstance.indentLine(i, "smart");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Applies automatic formatting to the specified range
|
||||
CodeMirror.defineExtension("autoFormatRange", function (from, to) {
|
||||
var cm = this;
|
||||
var outer = cm.getMode(), text = cm.getRange(from, to).split("\n");
|
||||
var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state);
|
||||
var tabSize = cm.getOption("tabSize");
|
||||
|
||||
var out = "", lines = 0, atSol = from.ch == 0;
|
||||
function newline() {
|
||||
out += "\n";
|
||||
atSol = true;
|
||||
++lines;
|
||||
}
|
||||
|
||||
for (var i = 0; i < text.length; ++i) {
|
||||
var stream = new CodeMirror.StringStream(text[i], tabSize);
|
||||
while (!stream.eol()) {
|
||||
var inner = CodeMirror.innerMode(outer, state);
|
||||
var style = outer.token(stream, state), cur = stream.current();
|
||||
stream.start = stream.pos;
|
||||
if (!atSol || /\S/.test(cur)) {
|
||||
out += cur;
|
||||
atSol = false;
|
||||
}
|
||||
if (!atSol && inner.mode.newlineAfterToken &&
|
||||
inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i+1] || "", inner.state))
|
||||
newline();
|
||||
}
|
||||
if (!stream.pos && outer.blankLine) outer.blankLine(state);
|
||||
if (!atSol) newline();
|
||||
}
|
||||
|
||||
cm.operation(function () {
|
||||
cm.replaceRange(out, from, to);
|
||||
for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur)
|
||||
cm.indentLine(cur, "smart");
|
||||
cm.setSelection(from, cm.getCursor(false));
|
||||
});
|
||||
});
|
||||
})();
|
||||
138
codemirror/lib/util/javascript-hint.js
vendored
Normal file
138
codemirror/lib/util/javascript-hint.js
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
(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, 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, {line: cur.line, ch: tprop.start});
|
||||
if (tprop.string != ".") return;
|
||||
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
|
||||
if (tprop.string == ')') {
|
||||
var level = 1;
|
||||
do {
|
||||
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
|
||||
switch (tprop.string) {
|
||||
case ')': level++; break;
|
||||
case '(': level--; break;
|
||||
default: break;
|
||||
}
|
||||
} while (level > 0);
|
||||
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
|
||||
if (tprop.type == 'variable')
|
||||
tprop.type = 'function';
|
||||
else return; // no clue
|
||||
}
|
||||
if (!context) var context = [];
|
||||
context.push(tprop);
|
||||
}
|
||||
return {list: getCompletions(token, context, keywords, options),
|
||||
from: {line: cur.line, ch: token.start},
|
||||
to: {line: cur.line, ch: token.end}};
|
||||
}
|
||||
|
||||
CodeMirror.javascriptHint = function(editor, 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 == "variable") {
|
||||
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;
|
||||
}
|
||||
})();
|
||||
51
codemirror/lib/util/loadmode.js
vendored
Normal file
51
codemirror/lib/util/loadmode.js
vendored
Normal 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"));
|
||||
});
|
||||
};
|
||||
}());
|
||||
46
codemirror/lib/util/match-highlighter.js
vendored
Normal file
46
codemirror/lib/util/match-highlighter.js
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// Define match-highlighter commands. Depends on searchcursor.js
|
||||
// Use by attaching the following function call to the cursorActivity event:
|
||||
//myCodeMirror.matchHighlight(minChars);
|
||||
// And including a special span.CodeMirror-matchhighlight css class (also optionally a separate one for .CodeMirror-focused -- see demo matchhighlighter.html)
|
||||
|
||||
(function() {
|
||||
var DEFAULT_MIN_CHARS = 2;
|
||||
|
||||
function MatchHighlightState() {
|
||||
this.marked = [];
|
||||
}
|
||||
function getMatchHighlightState(cm) {
|
||||
return cm._matchHighlightState || (cm._matchHighlightState = new MatchHighlightState());
|
||||
}
|
||||
|
||||
function clearMarks(cm) {
|
||||
var state = getMatchHighlightState(cm);
|
||||
for (var i = 0; i < state.marked.length; ++i)
|
||||
state.marked[i].clear();
|
||||
state.marked = [];
|
||||
}
|
||||
|
||||
function markDocument(cm, className, minChars) {
|
||||
clearMarks(cm);
|
||||
minChars = (typeof minChars !== 'undefined' ? minChars : DEFAULT_MIN_CHARS);
|
||||
if (cm.somethingSelected() && cm.getSelection().replace(/^\s+|\s+$/g, "").length >= minChars) {
|
||||
var state = getMatchHighlightState(cm);
|
||||
var query = cm.getSelection();
|
||||
cm.operation(function() {
|
||||
if (cm.lineCount() < 2000) { // This is too expensive on big documents.
|
||||
for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
|
||||
//Only apply matchhighlight to the matches other than the one actually selected
|
||||
if (cursor.from().line !== cm.getCursor(true).line ||
|
||||
cursor.from().ch !== cm.getCursor(true).ch)
|
||||
state.marked.push(cm.markText(cursor.from(), cursor.to(),
|
||||
{className: className}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
CodeMirror.defineExtension("matchHighlight", function(className, minChars) {
|
||||
markDocument(this, className, minChars);
|
||||
});
|
||||
})();
|
||||
63
codemirror/lib/util/matchbrackets.js
vendored
Normal file
63
codemirror/lib/util/matchbrackets.js
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
(function() {
|
||||
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
|
||||
function findMatchingBracket(cm) {
|
||||
var cur = cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
|
||||
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
|
||||
if (!match) return null;
|
||||
var forward = match.charAt(1) == ">", d = forward ? 1 : -1;
|
||||
var style = cm.getTokenAt({line: cur.line, ch: pos + 1}).type;
|
||||
|
||||
var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
|
||||
function scan(line, lineNo, start) {
|
||||
if (!line.text) return;
|
||||
var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1;
|
||||
if (start != null) pos = start + d;
|
||||
for (; pos != end; pos += d) {
|
||||
var ch = line.text.charAt(pos);
|
||||
if (re.test(ch) && cm.getTokenAt({line: lineNo, ch: pos + 1}).type == style) {
|
||||
var match = matching[ch];
|
||||
if (match.charAt(1) == ">" == forward) stack.push(ch);
|
||||
else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
|
||||
else if (!stack.length) return {pos: pos, match: true};
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) {
|
||||
if (i == cur.line) found = scan(line, i, pos);
|
||||
else found = scan(cm.getLineHandle(i), i);
|
||||
if (found) break;
|
||||
}
|
||||
return {from: {line: cur.line, ch: pos}, to: found && {line: i, ch: found.pos}, match: found && found.match};
|
||||
}
|
||||
|
||||
function matchBrackets(cm, autoclear) {
|
||||
var found = findMatchingBracket(cm);
|
||||
if (!found) return;
|
||||
var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
|
||||
var one = cm.markText(found.from, {line: found.from.line, ch: found.from.ch + 1},
|
||||
{className: style});
|
||||
var two = found.to && cm.markText(found.to, {line: found.to.line, ch: found.to.ch + 1},
|
||||
{className: style});
|
||||
var clear = function() {
|
||||
cm.operation(function() { one.clear(); two && two.clear(); });
|
||||
};
|
||||
if (autoclear) setTimeout(clear, 800);
|
||||
else return clear;
|
||||
}
|
||||
|
||||
var currentlyHighlighted = null;
|
||||
function doMatchBrackets(cm) {
|
||||
cm.operation(function() {
|
||||
if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
|
||||
if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false);
|
||||
});
|
||||
}
|
||||
|
||||
CodeMirror.defineOption("matchBrackets", false, function(cm, val) {
|
||||
if (val) cm.on("cursorActivity", doMatchBrackets);
|
||||
else cm.off("cursorActivity", doMatchBrackets);
|
||||
});
|
||||
|
||||
CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
|
||||
CodeMirror.defineExtension("findMatchingBracket", function(){return findMatchingBracket(this);});
|
||||
})();
|
||||
95
codemirror/lib/util/multiplex.js
vendored
Normal file
95
codemirror/lib/util/multiplex.js
vendored
Normal 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};
|
||||
}
|
||||
};
|
||||
};
|
||||
59
codemirror/lib/util/overlay.js
vendored
Normal file
59
codemirror/lib/util/overlay.js
vendored
Normal 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);
|
||||
}
|
||||
};
|
||||
};
|
||||
117
codemirror/lib/util/pig-hint.js
vendored
Normal file
117
codemirror/lib/util/pig-hint.js
vendored
Normal 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: {line: cur.line, ch: token.start},
|
||||
to: {line: cur.line, ch: 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;
|
||||
}
|
||||
})();
|
||||
90
codemirror/lib/util/runmode-standalone.js
vendored
Normal file
90
codemirror/lib/util/runmode-standalone.js
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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") {
|
||||
function cased(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;
|
||||
}
|
||||
}
|
||||
};
|
||||
52
codemirror/lib/util/runmode.js
vendored
Normal file
52
codemirror/lib/util/runmode.js
vendored
Normal 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;
|
||||
}
|
||||
}
|
||||
};
|
||||
131
codemirror/lib/util/search.js
vendored
Normal file
131
codemirror/lib/util/search.js
vendored
Normal 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 ? {line: cm.lineCount() - 1} : {line: 0, ch: 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());
|
||||
function advance() {
|
||||
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]);
|
||||
}
|
||||
function doReplace(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);};
|
||||
})();
|
||||
119
codemirror/lib/util/searchcursor.js
vendored
Normal file
119
codemirror/lib/util/searchcursor.js
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
(function(){
|
||||
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) : {line: 0, ch: 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), match = query.exec(line), start = 0;
|
||||
while (match) {
|
||||
start += match.index + 1;
|
||||
line = line.slice(start);
|
||||
query.lastIndex = 0;
|
||||
var newmatch = query.exec(line);
|
||||
if (newmatch) match = newmatch;
|
||||
else break;
|
||||
}
|
||||
start--;
|
||||
} else {
|
||||
query.lastIndex = pos.ch;
|
||||
var line = cm.getLine(pos.line), match = query.exec(line),
|
||||
start = match && match.index;
|
||||
}
|
||||
if (match)
|
||||
return {from: {line: pos.line, ch: start},
|
||||
to: {line: pos.line, ch: 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)
|
||||
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: {line: pos.line, ch: match},
|
||||
to: {line: pos.line, ch: 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 = {line: pos.line, ch: offsetA}, end = {line: ln, ch: 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 = {line: line, ch: 0};
|
||||
self.pos = {from: pos, to: pos};
|
||||
self.atOccurrence = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (this.pos = this.matches(reverse, pos)) {
|
||||
this.atOccurrence = true;
|
||||
return this.pos.match || true;
|
||||
}
|
||||
if (reverse) {
|
||||
if (!pos.line) return savePosAndFail(0);
|
||||
pos = {line: pos.line-1, ch: this.cm.getLine(pos.line-1).length};
|
||||
}
|
||||
else {
|
||||
var maxLine = this.cm.lineCount();
|
||||
if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
|
||||
pos = {line: pos.line+1, ch: 0};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
from: function() {if (this.atOccurrence) return this.pos.from;},
|
||||
to: function() {if (this.atOccurrence) return this.pos.to;},
|
||||
|
||||
replace: function(newText) {
|
||||
var self = this;
|
||||
if (this.atOccurrence)
|
||||
self.pos.to = this.cm.replaceRange(newText, self.pos.from, self.pos.to);
|
||||
}
|
||||
};
|
||||
|
||||
CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
|
||||
return new SearchCursor(this, query, pos, caseFold);
|
||||
});
|
||||
})();
|
||||
16
codemirror/lib/util/simple-hint.css
vendored
Normal file
16
codemirror/lib/util/simple-hint.css
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
.CodeMirror-completions {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
||||
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
|
||||
}
|
||||
.CodeMirror-completions select {
|
||||
background: #fafafa;
|
||||
outline: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: monospace;
|
||||
}
|
||||
102
codemirror/lib/util/simple-hint.js
vendored
Normal file
102
codemirror/lib/util/simple-hint.js
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
(function() {
|
||||
CodeMirror.simpleHint = function(editor, getHints, givenOptions) {
|
||||
// Determine effective options based on given values and defaults.
|
||||
var options = {}, defaults = CodeMirror.simpleHint.defaults;
|
||||
for (var opt in defaults)
|
||||
if (defaults.hasOwnProperty(opt))
|
||||
options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];
|
||||
|
||||
function collectHints(previousToken) {
|
||||
// We want a single cursor position.
|
||||
if (editor.somethingSelected()) return;
|
||||
|
||||
var tempToken = editor.getTokenAt(editor.getCursor());
|
||||
|
||||
// Don't show completions if token has changed and the option is set.
|
||||
if (options.closeOnTokenChange && previousToken != null &&
|
||||
(tempToken.start != previousToken.start || tempToken.type != previousToken.type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var result = getHints(editor, givenOptions);
|
||||
if (!result || !result.list.length) return;
|
||||
var completions = result.list;
|
||||
function insert(str) {
|
||||
editor.replaceRange(str, result.from, result.to);
|
||||
}
|
||||
// When there is only one completion, use it directly.
|
||||
if (options.completeSingle && completions.length == 1) {
|
||||
insert(completions[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Build the select widget
|
||||
var complete = document.createElement("div");
|
||||
complete.className = "CodeMirror-completions";
|
||||
var sel = complete.appendChild(document.createElement("select"));
|
||||
// Opera doesn't move the selection when pressing up/down in a
|
||||
// multi-select, but it does properly support the size property on
|
||||
// single-selects, so no multi-select is necessary.
|
||||
if (!window.opera) sel.multiple = true;
|
||||
for (var i = 0; i < completions.length; ++i) {
|
||||
var opt = sel.appendChild(document.createElement("option"));
|
||||
opt.appendChild(document.createTextNode(completions[i]));
|
||||
}
|
||||
sel.firstChild.selected = true;
|
||||
sel.size = Math.min(10, completions.length);
|
||||
var pos = editor.cursorCoords(options.alignWithWord ? result.from : null);
|
||||
complete.style.left = pos.left + "px";
|
||||
complete.style.top = pos.bottom + "px";
|
||||
document.body.appendChild(complete);
|
||||
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
|
||||
var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
|
||||
if(winW - pos.left < sel.clientWidth)
|
||||
complete.style.left = (pos.left - sel.clientWidth) + "px";
|
||||
// Hack to hide the scrollbar.
|
||||
if (completions.length <= 10)
|
||||
complete.style.width = (sel.clientWidth - 1) + "px";
|
||||
|
||||
var done = false;
|
||||
function close() {
|
||||
if (done) return;
|
||||
done = true;
|
||||
complete.parentNode.removeChild(complete);
|
||||
}
|
||||
function pick() {
|
||||
insert(completions[sel.selectedIndex]);
|
||||
close();
|
||||
setTimeout(function(){editor.focus();}, 50);
|
||||
}
|
||||
CodeMirror.on(sel, "blur", close);
|
||||
CodeMirror.on(sel, "keydown", function(event) {
|
||||
var code = event.keyCode;
|
||||
// Enter
|
||||
if (code == 13) {CodeMirror.e_stop(event); pick();}
|
||||
// Escape
|
||||
else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
|
||||
else if (code != 38 && code != 40 && code != 33 && code != 34 && !CodeMirror.isModifierKey(event)) {
|
||||
close(); editor.focus();
|
||||
// Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
|
||||
editor.triggerOnKeyDown(event);
|
||||
// Don't show completions if the code is backspace and the option is set.
|
||||
if (!options.closeOnBackspace || code != 8) {
|
||||
setTimeout(function(){collectHints(tempToken);}, 50);
|
||||
}
|
||||
}
|
||||
});
|
||||
CodeMirror.on(sel, "dblclick", pick);
|
||||
|
||||
sel.focus();
|
||||
// Opera sometimes ignores focusing a freshly created node
|
||||
if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100);
|
||||
return true;
|
||||
}
|
||||
return collectHints();
|
||||
};
|
||||
CodeMirror.simpleHint.defaults = {
|
||||
closeOnBackspace: true,
|
||||
closeOnTokenChange: false,
|
||||
completeSingle: true,
|
||||
alignWithWord: true
|
||||
};
|
||||
})();
|
||||
131
codemirror/lib/util/xml-hint.js
vendored
Normal file
131
codemirror/lib/util/xml-hint.js
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
|
||||
(function() {
|
||||
|
||||
CodeMirror.xmlHints = [];
|
||||
|
||||
CodeMirror.xmlHint = function(cm, simbol) {
|
||||
|
||||
if(simbol.length > 0) {
|
||||
var cursor = cm.getCursor();
|
||||
cm.replaceSelection(simbol);
|
||||
cursor = {line: cursor.line, ch: cursor.ch + 1};
|
||||
cm.setCursor(cursor);
|
||||
}
|
||||
|
||||
CodeMirror.simpleHint(cm, getHint);
|
||||
};
|
||||
|
||||
var getHint = function(cm) {
|
||||
|
||||
var cursor = cm.getCursor();
|
||||
|
||||
if (cursor.ch > 0) {
|
||||
|
||||
var text = cm.getRange({line: 0, ch: 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: { line: cursor.line, ch: cursor.ch - typed.length },
|
||||
to: cursor
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
var getActiveElement = function(text) {
|
||||
|
||||
var element = '';
|
||||
|
||||
if(text.length >= 0) {
|
||||
|
||||
var regex = new RegExp('<([^!?][^\\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 '';
|
||||
};
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user