diff --git a/applications/admin/languages/it.py b/applications/admin/languages/it.py
index c97b6b39..d6776613 100644
--- a/applications/admin/languages/it.py
+++ b/applications/admin/languages/it.py
@@ -55,6 +55,7 @@
'cannot create file': 'impossibile creare il file',
'cannot upload file "%(filename)s"': 'impossibile caricare il file "%(filename)s"',
'Change admin password': 'change admin password',
+'change editor settings': 'change editor settings',
'change password': 'cambia password',
'check all': 'controlla tutto',
'Check for upgrades': 'check for upgrades',
@@ -125,12 +126,14 @@
'Editing italo': 'Editing italo',
'Editing italo3': 'Editing italo3',
'Editing Language file': 'Modifica file linguaggio',
+'Editing welcome': 'Editing welcome',
'Enterprise Web Framework': 'Enterprise Web Framework',
'Error logs for "%(app)s"': 'Log degli errori per "%(app)s"',
'Error snapshot': 'Error snapshot',
'Error ticket': 'Error ticket',
'Errors': 'errori',
'Exception instance attributes': 'Exception instance attributes',
+'Exit Fullscreen': 'Exit Fullscreen',
'Expand Abbreviation': 'Expand Abbreviation',
'export as csv file': 'esporta come file CSV',
'exposes': 'espone',
diff --git a/applications/admin/static/codemirror/CONTRIBUTING.md b/applications/admin/static/codemirror/CONTRIBUTING.md
index 4e040ff1..8938f620 100644
--- a/applications/admin/static/codemirror/CONTRIBUTING.md
+++ b/applications/admin/static/codemirror/CONTRIBUTING.md
@@ -4,12 +4,12 @@
- [Submitting bug reports](#submitting-bug-reports-)
- [Contributing code](#contributing-code-)
-## Getting help [^](#how-to-contribute)
+## Getting help
Community discussion, questions, and informal bug reporting is done on the
[CodeMirror Google group](http://groups.google.com/group/codemirror).
-## Submitting bug reports [^](#how-to-contribute)
+## Submitting bug reports
The preferred way to report bugs is to use the
[GitHub issue tracker](http://github.com/marijnh/CodeMirror/issues). Before
@@ -45,7 +45,7 @@ should be asked on the
[jsbin.com](http://jsbin.com/ihunin/edit), enter it there, press save, and
include the resulting link in your bug report.
-## Contributing code [^](#how-to-contribute)
+## Contributing code
- Make sure you have a [GitHub Account](https://github.com/signup/free)
- Fork [CodeMirror](https://github.com/marijnh/CodeMirror/)
diff --git a/applications/admin/static/codemirror/LICENSE b/applications/admin/static/codemirror/LICENSE
index 482d55eb..442d11cd 100644
--- a/applications/admin/static/codemirror/LICENSE
+++ b/applications/admin/static/codemirror/LICENSE
@@ -1,4 +1,4 @@
-Copyright (C) 2013 by Marijn Haverbeke
+Copyright (C) 2013 by Marijn Haverbeke and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -17,7 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-
-Please note that some subdirectories of the CodeMirror distribution
-include their own LICENSE files, and are released under different
-licences.
diff --git a/applications/admin/static/codemirror/addon/comment/comment.js b/applications/admin/static/codemirror/addon/comment/comment.js
index 3c767446..cd2123e1 100644
--- a/applications/admin/static/codemirror/addon/comment/comment.js
+++ b/applications/admin/static/codemirror/addon/comment/comment.js
@@ -17,7 +17,7 @@
CodeMirror.defineExtension("lineComment", function(from, to, options) {
if (!options) options = noOptions;
- var self = this, mode = CodeMirror.innerMode(self.getMode(), self.getTokenAt(from).state).mode;
+ var self = this, mode = self.getModeAt(from);
var commentString = options.lineComment || mode.lineComment;
if (!commentString) {
if (options.blockCommentStart || mode.blockCommentStart) {
@@ -52,7 +52,7 @@
CodeMirror.defineExtension("blockComment", function(from, to, options) {
if (!options) options = noOptions;
- var self = this, mode = CodeMirror.innerMode(self.getMode(), self.getTokenAt(from).state).mode;
+ var self = this, mode = self.getModeAt(from);
var startString = options.blockCommentStart || mode.blockCommentStart;
var endString = options.blockCommentEnd || mode.blockCommentEnd;
if (!startString || !endString) {
@@ -85,7 +85,7 @@
CodeMirror.defineExtension("uncomment", function(from, to, options) {
if (!options) options = noOptions;
- var self = this, mode = CodeMirror.innerMode(self.getMode(), self.getTokenAt(from).state).mode;
+ var self = this, mode = self.getModeAt(from);
var end = Math.min(to.line, self.lastLine()), start = Math.min(from.line, end);
// Try finding line comments
diff --git a/applications/admin/static/codemirror/addon/display/fullscreen.css b/applications/admin/static/codemirror/addon/display/fullscreen.css
new file mode 100644
index 00000000..437acd89
--- /dev/null
+++ b/applications/admin/static/codemirror/addon/display/fullscreen.css
@@ -0,0 +1,6 @@
+.CodeMirror-fullscreen {
+ position: fixed;
+ top: 0; left: 0; right: 0; bottom: 0;
+ height: auto;
+ z-index: 9;
+}
diff --git a/applications/admin/static/codemirror/addon/display/fullscreen.js b/applications/admin/static/codemirror/addon/display/fullscreen.js
new file mode 100644
index 00000000..3c31e97a
--- /dev/null
+++ b/applications/admin/static/codemirror/addon/display/fullscreen.js
@@ -0,0 +1,30 @@
+(function() {
+ "use strict";
+
+ CodeMirror.defineOption("fullScreen", false, function(cm, val, old) {
+ if (old == CodeMirror.Init) old = false;
+ if (!old == !val) return;
+ if (val) setFullscreen(cm);
+ else setNormal(cm);
+ });
+
+ function setFullscreen(cm) {
+ var wrap = cm.getWrapperElement();
+ cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset,
+ width: wrap.style.width, height: wrap.style.height};
+ wrap.style.width = wrap.style.height = "";
+ wrap.className += " CodeMirror-fullscreen";
+ document.documentElement.style.overflow = "hidden";
+ cm.refresh();
+ }
+
+ function setNormal(cm) {
+ var wrap = cm.getWrapperElement();
+ wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, "");
+ document.documentElement.style.overflow = "";
+ var info = cm.state.fullScreenRestore;
+ wrap.style.width = info.width; wrap.style.height = info.height;
+ window.scrollTo(info.scrollLeft, info.scrollTop);
+ cm.refresh();
+ }
+})();
diff --git a/applications/admin/static/codemirror/addon/edit/closebrackets.js b/applications/admin/static/codemirror/addon/edit/closebrackets.js
index 6fbf38ae..88718b77 100644
--- a/applications/admin/static/codemirror/addon/edit/closebrackets.js
+++ b/applications/admin/static/codemirror/addon/edit/closebrackets.js
@@ -54,7 +54,9 @@
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);
+ var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch), curChar = cur.ch > 0 ? line.charAt(cur.ch - 1) : "";
+ if (left == right && CodeMirror.isWordChar(curChar))
+ return CodeMirror.Pass;
if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || SPACE_CHAR_REGEX.test(nextChar))
cm.replaceSelection(left + right, {head: ahead, anchor: ahead});
else
diff --git a/applications/admin/static/codemirror/addon/edit/closetag.js b/applications/admin/static/codemirror/addon/edit/closetag.js
index 454dfea5..0bc3e8be 100644
--- a/applications/admin/static/codemirror/addon/edit/closetag.js
+++ b/applications/admin/static/codemirror/addon/edit/closetag.js
@@ -27,9 +27,9 @@
if (val && (old == CodeMirror.Init || !old)) {
var map = {name: "autoCloseTags"};
if (typeof val != "object" || val.whenClosing)
- map["'/'"] = function(cm) { return autoCloseTag(cm, '/'); };
+ map["'/'"] = function(cm) { return autoCloseSlash(cm); };
if (typeof val != "object" || val.whenOpening)
- map["'>'"] = function(cm) { return autoCloseTag(cm, '>'); };
+ map["'>'"] = function(cm) { return autoCloseGT(cm); };
cm.addKeyMap(map);
} else if (!val && (old != CodeMirror.Init && old)) {
cm.removeKeyMap("autoCloseTags");
@@ -41,40 +41,41 @@
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) {
+ function autoCloseGT(cm) {
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;
+ if (inner.mode.name != "xml" || !state.tagName) 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("/") == (tok.string.length - 1) || // match something like
- dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1)
- return CodeMirror.Pass;
+ 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("/") == (tok.string.length - 1) || // match something like
+ 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;
+ 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 CodeMirror.Pass;
+ }
+
+ function autoCloseSlash(cm) {
+ var pos = cm.getCursor(), tok = cm.getTokenAt(pos);
+ var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
+ if (tok.string.charAt(0) != "<" || inner.mode.name != "xml") return CodeMirror.Pass;
+
+ var tagName = state.context && state.context.tagName;
+ if (tagName) cm.replaceSelection("/" + tagName + ">", "end");
}
function indexOf(collection, elt) {
diff --git a/applications/admin/static/codemirror/addon/edit/continuecomment.js b/applications/admin/static/codemirror/addon/edit/continuecomment.js
deleted file mode 100644
index 30802622..00000000
--- a/applications/admin/static/codemirror/addon/edit/continuecomment.js
+++ /dev/null
@@ -1,44 +0,0 @@
-(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);
- });
-})();
diff --git a/applications/admin/static/codemirror/addon/fold/brace-fold.js b/applications/admin/static/codemirror/addon/fold/brace-fold.js
index e35115b8..2560b2b9 100644
--- a/applications/admin/static/codemirror/addon/fold/brace-fold.js
+++ b/applications/admin/static/codemirror/addon/fold/brace-fold.js
@@ -1,10 +1,10 @@
-CodeMirror.braceRangeFinder = function(cm, start) {
+CodeMirror.registerHelper("fold", "brace", function(cm, start) {
var line = start.line, lineText = cm.getLine(line);
var startCh, tokenType;
function findOpening(openCh) {
for (var at = start.ch, pass = 0;;) {
- var found = lineText.lastIndexOf(openCh, at - 1);
+ var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1);
if (found == -1) {
if (pass == 1) break;
pass = 1;
@@ -12,7 +12,7 @@ CodeMirror.braceRangeFinder = function(cm, start) {
continue;
}
if (pass == 1 && found < start.ch) break;
- tokenType = cm.getTokenAt(CodeMirror.Pos(line, found + 1)).type;
+ tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
if (!/^(comment|string)/.test(tokenType)) return found + 1;
at = found - 1;
}
@@ -34,7 +34,7 @@ CodeMirror.braceRangeFinder = function(cm, start) {
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 (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) {
if (pos == nextOpen) ++count;
else if (!--count) { end = i; endCh = pos; break outer; }
}
@@ -44,9 +44,10 @@ CodeMirror.braceRangeFinder = function(cm, start) {
if (end == null || line == end && endCh == startCh) return;
return {from: CodeMirror.Pos(line, startCh),
to: CodeMirror.Pos(end, endCh)};
-};
+});
+CodeMirror.braceRangeFinder = CodeMirror.fold.brace; // deprecated
-CodeMirror.importRangeFinder = function(cm, start) {
+CodeMirror.registerHelper("fold", "import", function(cm, start) {
function hasImport(line) {
if (line < cm.firstLine() || line > cm.lastLine()) return null;
var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
@@ -68,9 +69,10 @@ CodeMirror.importRangeFinder = function(cm, start) {
end = next.end;
}
return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end};
-};
+});
+CodeMirror.importRangeFinder = CodeMirror.fold["import"]; // deprecated
-CodeMirror.includeRangeFinder = function(cm, start) {
+CodeMirror.registerHelper("fold", "include", function(cm, start) {
function hasInclude(line) {
if (line < cm.firstLine() || line > cm.lastLine()) return null;
var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
@@ -87,4 +89,5 @@ CodeMirror.includeRangeFinder = function(cm, start) {
}
return {from: CodeMirror.Pos(start, has + 1),
to: cm.clipPos(CodeMirror.Pos(end))};
-};
+});
+CodeMirror.includeRangeFinder = CodeMirror.fold.include; // deprecated
diff --git a/applications/admin/static/codemirror/addon/fold/foldcode.js b/applications/admin/static/codemirror/addon/fold/foldcode.js
index 2743d3e2..931c3726 100644
--- a/applications/admin/static/codemirror/addon/fold/foldcode.js
+++ b/applications/admin/static/codemirror/addon/fold/foldcode.js
@@ -2,7 +2,8 @@
"use strict";
function doFold(cm, pos, options) {
- var finder = options.call ? options : (options && options.rangeFinder);
+ var finder = options && (options.call ? options : options.rangeFinder);
+ if (!finder) finder = cm.getHelper(pos, "fold");
if (!finder) return;
if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
var minSize = options && options.minFoldSize || 0;
@@ -29,12 +30,16 @@
if (!range || range.cleared) return;
var myWidget = makeWidget(options);
- CodeMirror.on(myWidget, "mousedown", function() {myRange.clear();});
+ CodeMirror.on(myWidget, "mousedown", function() { myRange.clear(); });
var myRange = cm.markText(range.from, range.to, {
replacedWith: myWidget,
clearOnEnter: true,
__isFold: true
});
+ myRange.on("clear", function(from, to) {
+ CodeMirror.signal(cm, "unfold", cm, from, to);
+ });
+ CodeMirror.signal(cm, "fold", cm, range.from, range.to);
}
function makeWidget(options) {
@@ -56,7 +61,7 @@
// New-style interface
CodeMirror.defineExtension("foldCode", function(pos, options) { doFold(this, pos, options); });
- CodeMirror.combineRangeFinders = function() {
+ CodeMirror.registerHelper("fold", "combine", function() {
var funcs = Array.prototype.slice.call(arguments, 0);
return function(cm, start) {
for (var i = 0; i < funcs.length; ++i) {
@@ -64,5 +69,5 @@
if (found) return found;
}
};
- };
+ });
})();
diff --git a/applications/admin/static/codemirror/addon/fold/indent-fold.js b/applications/admin/static/codemirror/addon/fold/indent-fold.js
index 94a0a1ff..fcbff966 100644
--- a/applications/admin/static/codemirror/addon/fold/indent-fold.js
+++ b/applications/admin/static/codemirror/addon/fold/indent-fold.js
@@ -1,4 +1,4 @@
-CodeMirror.indentRangeFinder = function(cm, start) {
+CodeMirror.registerHelper("fold", "indent", 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) {
@@ -8,4 +8,5 @@ CodeMirror.indentRangeFinder = function(cm, start) {
return {from: CodeMirror.Pos(start.line, firstLine.length),
to: CodeMirror.Pos(i, curLine.length)};
}
-};
+});
+CodeMirror.indentRangeFinder = CodeMirror.fold.indent; // deprecated
diff --git a/applications/admin/static/codemirror/addon/fold/xml-fold.js b/applications/admin/static/codemirror/addon/fold/xml-fold.js
index b764bc01..88a107c4 100644
--- a/applications/admin/static/codemirror/addon/fold/xml-fold.js
+++ b/applications/admin/static/codemirror/addon/fold/xml-fold.js
@@ -2,14 +2,17 @@
"use strict";
var Pos = CodeMirror.Pos;
+ function cmp(a, b) { return a.line - b.line || a.ch - b.ch; }
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");
- function Iter(cm, line, ch) {
+ function Iter(cm, line, ch, range) {
this.line = line; this.ch = ch;
this.cm = cm; this.text = cm.getLine(line);
+ this.min = range ? range.from : cm.firstLine();
+ this.max = range ? range.to - 1 : cm.lastLine();
}
function tagAt(iter, ch) {
@@ -18,13 +21,13 @@
}
function nextLine(iter) {
- if (iter.line >= iter.cm.lastLine()) return;
+ if (iter.line >= iter.max) return;
iter.ch = 0;
iter.text = iter.cm.getLine(++iter.line);
return true;
}
function prevLine(iter) {
- if (iter.line <= iter.cm.firstLine()) return;
+ if (iter.line <= iter.min) return;
iter.text = iter.cm.getLine(--iter.line);
iter.ch = iter.text.length;
return true;
@@ -43,7 +46,7 @@
}
function toTagStart(iter) {
for (;;) {
- var lt = iter.text.lastIndexOf("<", iter.ch - 1);
+ var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1;
if (lt == -1) { if (prevLine(iter)) continue; else return; }
if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; }
xmlTagStart.lastIndex = lt;
@@ -65,7 +68,7 @@
}
function toPrevTag(iter) {
for (;;) {
- var gt = iter.text.lastIndexOf(">", iter.ch - 1);
+ var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1;
if (gt == -1) { if (prevLine(iter)) continue; else return; }
if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; }
var lastSlash = iter.text.lastIndexOf("/", gt);
@@ -121,7 +124,7 @@
}
}
- CodeMirror.tagRangeFinder = function(cm, start) {
+ CodeMirror.registerHelper("fold", "xml", function(cm, start) {
var iter = new Iter(cm, start.line, 0);
for (;;) {
var openTag = toNextTag(iter), end;
@@ -132,27 +135,31 @@
return close && {from: start, to: close.from};
}
}
- };
+ });
+ CodeMirror.tagRangeFinder = CodeMirror.fold.xml; // deprecated
- CodeMirror.findMatchingTag = function(cm, pos) {
- var iter = new Iter(cm, pos.line, pos.ch);
- var end = toTagEnd(iter), start = toTagStart(iter);
- if (!end || end == "selfClose" || !start) return;
+ CodeMirror.findMatchingTag = function(cm, pos, range) {
+ var iter = new Iter(cm, pos.line, pos.ch, range);
+ if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
+ var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
+ var start = end && toTagStart(iter);
+ if (!end || end == "selfClose" || !start || cmp(iter, pos) > 0) return;
+ var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
if (start[1]) { // closing tag
- return findMatchingOpen(iter, start[2]);
+ return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
} else { // opening tag
- toTagEnd(iter);
- return findMatchingClose(iter, start[2]);
+ iter = new Iter(cm, to.line, to.ch, range);
+ return {open: here, close: findMatchingClose(iter, start[2]), at: "open"};
}
};
- CodeMirror.findEnclosingTag = function(cm, pos) {
- var iter = new Iter(cm, pos.line, pos.ch);
+ CodeMirror.findEnclosingTag = function(cm, pos, range) {
+ var iter = new Iter(cm, pos.line, pos.ch, range);
for (;;) {
var open = findMatchingOpen(iter);
if (!open) break;
- var forward = new Iter(cm, pos.line, pos.ch);
+ var forward = new Iter(cm, pos.line, pos.ch, range);
var close = findMatchingClose(forward, open.tag);
if (close) return {open: open, close: close};
}
diff --git a/applications/admin/static/codemirror/addon/hint/html-hint.js b/applications/admin/static/codemirror/addon/hint/html-hint.js
index 23238df0..cf256851 100755
--- a/applications/admin/static/codemirror/addon/hint/html-hint.js
+++ b/applications/admin/static/codemirror/addon/hint/html-hint.js
@@ -327,9 +327,11 @@
populate(data[tag]);
CodeMirror.htmlSchema = data;
- CodeMirror.htmlHint = function(cm, options) {
+ function htmlHint(cm, options) {
var local = {schemaInfo: data};
if (options) for (var opt in options) local[opt] = options[opt];
- return CodeMirror.xmlHint(cm, local);
- };
+ return CodeMirror.hint.xml(cm, local);
+ }
+ CodeMirror.htmlHint = htmlHint; // deprecated
+ CodeMirror.registerHelper("hint", "html", htmlHint);
})();
diff --git a/applications/admin/static/codemirror/addon/hint/javascript-hint.js b/applications/admin/static/codemirror/addon/hint/javascript-hint.js
index b961c5ab..042fe132 100644
--- a/applications/admin/static/codemirror/addon/hint/javascript-hint.js
+++ b/applications/admin/static/codemirror/addon/hint/javascript-hint.js
@@ -56,11 +56,13 @@
to: Pos(cur.line, token.end)};
}
- CodeMirror.javascriptHint = function(editor, options) {
+ function javascriptHint(editor, options) {
return scriptHint(editor, javascriptKeywords,
function (e, cur) {return e.getTokenAt(cur);},
options);
};
+ CodeMirror.javascriptHint = javascriptHint; // deprecated
+ CodeMirror.registerHelper("hint", "javascript", javascriptHint);
function getCoffeeScriptToken(editor, cur) {
// This getToken, it is for coffeescript, imitates the behavior of
@@ -80,9 +82,11 @@
return token;
}
- CodeMirror.coffeescriptHint = function(editor, options) {
+ function coffeescriptHint(editor, options) {
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
- };
+ }
+ CodeMirror.coffeescriptHint = coffeescriptHint; // deprecated
+ CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);
var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
"toUpperCase toLowerCase split concat match replace search").split(" ");
diff --git a/applications/admin/static/codemirror/addon/hint/pig-hint.js b/applications/admin/static/codemirror/addon/hint/pig-hint.js
index d831ccfe..7ef336ce 100644
--- a/applications/admin/static/codemirror/addon/hint/pig-hint.js
+++ b/applications/admin/static/codemirror/addon/hint/pig-hint.js
@@ -1,4 +1,6 @@
(function () {
+ "use strict";
+
function forEach(arr, f) {
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
}
@@ -41,9 +43,11 @@
to: CodeMirror.Pos(cur.line, token.end)};
}
- CodeMirror.pigHint = function(editor) {
+ function pigHint(editor) {
return scriptHint(editor, pigKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
- };
+ }
+ CodeMirror.pigHint = pigHint; // deprecated
+ CodeMirror.registerHelper("hint", "pig", pigHint);
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 "
diff --git a/applications/admin/static/codemirror/addon/hint/python-hint.js b/applications/admin/static/codemirror/addon/hint/python-hint.js
index 60221b89..98d2a589 100644
--- a/applications/admin/static/codemirror/addon/hint/python-hint.js
+++ b/applications/admin/static/codemirror/addon/hint/python-hint.js
@@ -41,9 +41,11 @@
to: CodeMirror.Pos(cur.line, token.end)};
}
- CodeMirror.pythonHint = function(editor) {
+ function pythonHint(editor) {
return scriptHint(editor, pythonKeywordsU, function (e, cur) {return e.getTokenAt(cur);});
- };
+ }
+ CodeMirror.pythonHint = pythonHint; // deprecated
+ CodeMirror.registerHelper("hint", "python", pythonHint);
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";
diff --git a/applications/admin/static/codemirror/addon/hint/show-hint.js b/applications/admin/static/codemirror/addon/hint/show-hint.js
index 35e5cbb7..dbf41552 100644
--- a/applications/admin/static/codemirror/addon/hint/show-hint.js
+++ b/applications/admin/static/codemirror/addon/hint/show-hint.js
@@ -4,6 +4,8 @@
CodeMirror.showHint = function(cm, getHints, options) {
// We want a single cursor position.
if (cm.somethingSelected()) return;
+ if (getHints == null) getHints = cm.getHelper(cm.getCursor(), "hint");
+ if (getHints == null) return;
if (cm.state.completionActive) cm.state.completionActive.close();
@@ -25,10 +27,10 @@
Completion.prototype = {
close: function() {
if (!this.active()) return;
+ this.cm.state.completionActive = null;
if (this.widget) this.widget.close();
if (this.onClose) this.onClose();
- this.cm.state.completionActive = null;
CodeMirror.signal(this.cm, "endCompletion", this.cm);
},
@@ -65,24 +67,21 @@
finished = true;
completion.close();
completion.cm.off("cursorActivity", activity);
- CodeMirror.signal(data, "close");
- }
- function isDone() {
- if (finished) return true;
- if (!completion.widget) { done(); return true; }
+ if (data) CodeMirror.signal(data, "close");
}
function update() {
- if (isDone()) return;
+ if (finished) return;
+ CodeMirror.signal(data, "update");
if (completion.options.async)
completion.getHints(completion.cm, finishUpdate, completion.options);
else
finishUpdate(completion.getHints(completion.cm, completion.options));
}
- function finishUpdate(data) {
- if (isDone()) return;
+ function finishUpdate(data_) {
+ data = data_;
+ if (finished) return;
if (!data || !data.list.length) return done();
- completion.widget.close();
completion.widget = new Widget(completion, data);
}
@@ -91,10 +90,12 @@
var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
pos.ch < startPos.ch || completion.cm.somethingSelected() ||
- (pos.ch && closeOn.test(line.charAt(pos.ch - 1))))
+ (pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
completion.close();
- else
+ } else {
debounce = setTimeout(update, 170);
+ if (completion.widget) completion.widget.close();
+ }
}
this.cm.on("cursorActivity", activity);
this.onClose = done;
@@ -110,10 +111,10 @@
var baseMap = {
Up: function() {handle.moveFocus(-1);},
Down: function() {handle.moveFocus(1);},
- PageUp: function() {handle.moveFocus(-handle.menuSize());},
- PageDown: function() {handle.moveFocus(handle.menuSize());},
+ PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
+ PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
Home: function() {handle.setFocus(0);},
- End: function() {handle.setFocus(handle.length);},
+ End: function() {handle.setFocus(handle.length - 1);},
Enter: handle.pick,
Tab: handle.pick,
Esc: handle.close
@@ -166,6 +167,7 @@
// 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);
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
+ (options.container || document.body).appendChild(hints);
var box = hints.getBoundingClientRect();
var overlapX = box.right - winW, overlapY = box.bottom - winH;
if (overlapX > 0) {
@@ -186,10 +188,9 @@
}
hints.style.top = (top = pos.bottom - overlapY) + "px";
}
- (options.container || document.body).appendChild(hints);
cm.addKeyMap(this.keyMap = buildKeyMap(options, {
- moveFocus: function(n) { widget.changeActive(widget.selectedHint + n); },
+ moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
setFocus: function(n) { widget.changeActive(n); },
menuSize: function() { return widget.screenAmount(); },
length: completions.length,
@@ -249,8 +250,11 @@
this.completion.pick(this.data, this.selectedHint);
},
- changeActive: function(i) {
- i = Math.max(0, Math.min(i, this.data.list.length - 1));
+ changeActive: function(i, avoidWrap) {
+ if (i >= this.data.list.length)
+ i = avoidWrap ? this.data.list.length - 1 : 0;
+ else if (i < 0)
+ i = avoidWrap ? 0 : this.data.list.length - 1;
if (this.selectedHint == i) return;
var node = this.hints.childNodes[this.selectedHint];
node.className = node.className.replace(" CodeMirror-hint-active", "");
diff --git a/applications/admin/static/codemirror/addon/hint/xml-hint.js b/applications/admin/static/codemirror/addon/hint/xml-hint.js
index ea5b8d54..b6c1da2c 100644
--- a/applications/admin/static/codemirror/addon/hint/xml-hint.js
+++ b/applications/admin/static/codemirror/addon/hint/xml-hint.js
@@ -3,7 +3,7 @@
var Pos = CodeMirror.Pos;
- CodeMirror.xmlHint = function(cm, options) {
+ function getHints(cm, options) {
var tags = options && options.schemaInfo;
var quote = (options && options.quoteChar) || '"';
if (!tags) return;
@@ -61,5 +61,8 @@
from: replaceToken ? Pos(cur.line, token.start) : cur,
to: replaceToken ? Pos(cur.line, token.end) : cur
};
- };
+ }
+
+ CodeMirror.xmlHint = getHints; // deprecated
+ CodeMirror.registerHelper("hint", "xml", getHints);
})();
diff --git a/applications/admin/static/codemirror/addon/lint/coffeescript-lint.js b/applications/admin/static/codemirror/addon/lint/coffeescript-lint.js
index 9c30de51..7f55a294 100644
--- a/applications/admin/static/codemirror/addon/lint/coffeescript-lint.js
+++ b/applications/admin/static/codemirror/addon/lint/coffeescript-lint.js
@@ -1,6 +1,8 @@
// Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js
-CodeMirror.coffeeValidator = function(text) {
+// declare global: coffeelint
+
+CodeMirror.registerHelper("lint", "coffeescript", function(text) {
var found = [];
var parseError = function(err) {
var loc = err.lineNumber;
@@ -21,4 +23,5 @@ CodeMirror.coffeeValidator = function(text) {
message: e.message});
}
return found;
-};
+});
+CodeMirror.coffeeValidator = CodeMirror.lint.coffeescript; // deprecated
diff --git a/applications/admin/static/codemirror/addon/lint/javascript-lint.js b/applications/admin/static/codemirror/addon/lint/javascript-lint.js
index 9a815c82..7123ab7e 100644
--- a/applications/admin/static/codemirror/addon/lint/javascript-lint.js
+++ b/applications/admin/static/codemirror/addon/lint/javascript-lint.js
@@ -1,4 +1,6 @@
(function() {
+ "use strict";
+ // declare global: JSHINT
var bogus = [ "Dangerous comment" ];
@@ -9,18 +11,15 @@
"Unmatched ", " and instead saw", " is not defined",
"Unclosed string", "Stopping, unable to continue" ];
- function validator(options, text) {
+ function validator(text, options) {
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);
+ CodeMirror.registerHelper("lint", "javascript", validator);
+ CodeMirror.javascriptValidator = CodeMirror.lint.javascript; // deprecated
function cleanup(error) {
// All problems are warnings by default
diff --git a/applications/admin/static/codemirror/addon/lint/json-lint.js b/applications/admin/static/codemirror/addon/lint/json-lint.js
index 42b36abb..e10e11bc 100644
--- a/applications/admin/static/codemirror/addon/lint/json-lint.js
+++ b/applications/admin/static/codemirror/addon/lint/json-lint.js
@@ -1,6 +1,8 @@
// Depends on jsonlint.js from https://github.com/zaach/jsonlint
-CodeMirror.jsonValidator = function(text) {
+// declare global: jsonlint
+
+CodeMirror.registerHelper("lint", "json", function(text) {
var found = [];
jsonlint.parseError = function(str, hash) {
var loc = hash.loc;
@@ -11,4 +13,5 @@ CodeMirror.jsonValidator = function(text) {
try { jsonlint.parse(text); }
catch(e) {}
return found;
-};
+});
+CodeMirror.jsonValidator = CodeMirror.lint.json; // deprecated
diff --git a/applications/admin/static/codemirror/addon/lint/lint.css b/applications/admin/static/codemirror/addon/lint/lint.css
index eb15381f..e592b367 100644
--- a/applications/admin/static/codemirror/addon/lint/lint.css
+++ b/applications/admin/static/codemirror/addon/lint/lint.css
@@ -57,40 +57,16 @@
}
.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=");
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
}
.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==");
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-multiple {
- background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJEAQvB2JVdrAAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAD1JREFUCNdtjkESADAEAzemf69f66HMqGlOIhYiFRFRtSQBWAY7mzx+EDTL6sSgb1jTk7Q87rxyqe37fXsAa78gLyZnRgEAAAAASUVORK5CYII=");
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
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;
-}
-*/
\ No newline at end of file
diff --git a/applications/admin/static/codemirror/addon/lint/lint.js b/applications/admin/static/codemirror/addon/lint/lint.js
index 2e7cea19..b502ee41 100644
--- a/applications/admin/static/codemirror/addon/lint/lint.js
+++ b/applications/admin/static/codemirror/addon/lint/lint.js
@@ -1,4 +1,5 @@
-CodeMirror.validate = (function() {
+(function() {
+ "use strict";
var GUTTER_ID = "CodeMirror-lint-markers";
var SEVERITIES = /^(?:error|warning)$/;
@@ -52,9 +53,11 @@ CodeMirror.validate = (function() {
this.onMouseOver = function(e) { onMouseOver(cm, e); };
}
- function parseOptions(options) {
+ function parseOptions(cm, options) {
if (options instanceof Function) return {getAnnotations: options};
- else if (!options || !options.getAnnotations) throw new Error("Required option 'getAnnotations' missing (lint addon)");
+ if (!options || options === true) options = {};
+ if (!options.getAnnotations) options.getAnnotations = cm.getHelper(CodeMirror.Pos(0, 0), "lint");
+ if (!options.getAnnotations) throw new Error("Required option 'getAnnotations' missing (lint addon)");
return options;
}
@@ -109,7 +112,7 @@ CodeMirror.validate = (function() {
if (options.async)
options.getAnnotations(cm, updateLinting, options);
else
- updateLinting(cm, options.getAnnotations(cm.getValue()));
+ updateLinting(cm, options.getAnnotations(cm.getValue(), options));
}
function updateLinting(cm, annotationsNotSorted) {
@@ -175,7 +178,7 @@ CodeMirror.validate = (function() {
}
}
- CodeMirror.defineOption("lintWith", false, function(cm, val, old) {
+ function optionHandler(cm, val, old) {
if (old && old != CodeMirror.Init) {
clearMarks(cm);
cm.off("change", onChange);
@@ -186,12 +189,15 @@ CodeMirror.validate = (function() {
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.state.lint = new LintState(cm, parseOptions(val), hasLintGutter);
+ var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
cm.on("change", onChange);
if (state.options.tooltips != false)
CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
startLinting(cm);
}
- });
+ }
+
+ CodeMirror.defineOption("lintWith", false, optionHandler); // deprecated
+ CodeMirror.defineOption("lint", false, optionHandler); // deprecated
})();
diff --git a/applications/admin/static/codemirror/addon/merge/merge.css b/applications/admin/static/codemirror/addon/merge/merge.css
index 1f20f88a..63237fc8 100644
--- a/applications/admin/static/codemirror/addon/merge/merge.css
+++ b/applications/admin/static/codemirror/addon/merge/merge.css
@@ -1,24 +1,34 @@
-.CodeMirror-diff {
+.CodeMirror-merge {
position: relative;
border: 1px solid #ddd;
+ white-space: pre;
}
-.CodeMirror-diff, .CodeMirror-diff .CodeMirror {
+.CodeMirror-merge, .CodeMirror-merge .CodeMirror {
height: 350px;
}
-.CodeMirror-diff-2pane .CodeMirror-diff-pane { width: 47%; }
-.CodeMirror-diff-2pane .CodeMirror-diff-gap { width: 6%; }
-.CodeMirror-diff-3pane .CodeMirror-diff-pane { width: 31%; }
-.CodeMirror-diff-3pane .CodeMirror-diff-gap { width: 3.5%; }
+.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; }
+.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; }
+.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
+.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
-.CodeMirror-diff-pane {
- float: left;
+.CodeMirror-merge-pane {
+ display: inline-block;
+ white-space: normal;
+ vertical-align: top;
+}
+.CodeMirror-merge-pane-rightmost {
+ position: absolute;
+ right: 0px;
+ z-index: 1;
}
-.CodeMirror-diff-gap {
- float: left;
+.CodeMirror-merge-gap {
+ z-index: 2;
+ display: inline-block;
height: 100%;
+ -moz-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
border-left: 1px solid #ddd;
@@ -27,11 +37,11 @@
background: #f8f8f8;
}
-.CodeMirror-diff-scrolllock-wrap {
+.CodeMirror-merge-scrolllock-wrap {
position: absolute;
bottom: 0; left: 50%;
}
-.CodeMirror-diff-scrolllock {
+.CodeMirror-merge-scrolllock {
position: relative;
left: -50%;
cursor: pointer;
@@ -39,44 +49,44 @@
line-height: 1;
}
-.CodeMirror-diff-copybuttons-left, .CodeMirror-diff-copybuttons-right {
+.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
position: absolute;
left: 0; top: 0;
right: 0; bottom: 0;
line-height: 1;
}
-.CodeMirror-diff-copy {
+.CodeMirror-merge-copy {
position: absolute;
cursor: pointer;
color: #44c;
}
-.CodeMirror-diff-copybuttons-left .CodeMirror-diff-copy { left: 2px; }
-.CodeMirror-diff-copybuttons-right .CodeMirror-diff-copy { right: 2px; }
+.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
+.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
-.CodeMirror-diff-r-inserted, .CodeMirror-diff-l-inserted {
+.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
-.CodeMirror-diff-r-deleted, .CodeMirror-diff-l-deleted {
+.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
-.CodeMirror-diff-r-chunk { background: #ffffe0; }
-.CodeMirror-diff-r-chunk-start { border-top: 1px solid #ee8; }
-.CodeMirror-diff-r-chunk-end { border-bottom: 1px solid #ee8; }
-.CodeMirror-diff-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }
+.CodeMirror-merge-r-chunk { background: #ffffe0; }
+.CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; }
+.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; }
+.CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }
-.CodeMirror-diff-l-chunk { background: #eef; }
-.CodeMirror-diff-l-chunk-start { border-top: 1px solid #88e; }
-.CodeMirror-diff-l-chunk-end { border-bottom: 1px solid #88e; }
-.CodeMirror-diff-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
+.CodeMirror-merge-l-chunk { background: #eef; }
+.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
+.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
+.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
-.CodeMirror-diff-l-chunk.CodeMirror-diff-r-chunk { background: #dfd; }
-.CodeMirror-diff-l-chunk-start.CodeMirror-diff-r-chunk-start { border-top: 1px solid #4e4; }
-.CodeMirror-diff-l-chunk-end.CodeMirror-diff-r-chunk-end { border-bottom: 1px solid #4e4; }
+.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
+.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
+.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
diff --git a/applications/admin/static/codemirror/addon/merge/merge.js b/applications/admin/static/codemirror/addon/merge/merge.js
index b1125185..70341e4d 100644
--- a/applications/admin/static/codemirror/addon/merge/merge.js
+++ b/applications/admin/static/codemirror/addon/merge/merge.js
@@ -1,5 +1,6 @@
(function() {
"use strict";
+ // declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL
var Pos = CodeMirror.Pos;
var svgNS = "http://www.w3.org/2000/svg";
@@ -8,18 +9,18 @@
this.mv = mv;
this.type = type;
this.classes = type == "left"
- ? {chunk: "CodeMirror-diff-l-chunk",
- start: "CodeMirror-diff-l-chunk-start",
- end: "CodeMirror-diff-l-chunk-end",
- insert: "CodeMirror-diff-l-inserted",
- del: "CodeMirror-diff-l-deleted",
- connect: "CodeMirror-diff-l-connect"}
- : {chunk: "CodeMirror-diff-r-chunk",
- start: "CodeMirror-diff-r-chunk-start",
- end: "CodeMirror-diff-r-chunk-end",
- insert: "CodeMirror-diff-r-inserted",
- del: "CodeMirror-diff-r-deleted",
- connect: "CodeMirror-diff-r-connect"};
+ ? {chunk: "CodeMirror-merge-l-chunk",
+ start: "CodeMirror-merge-l-chunk-start",
+ end: "CodeMirror-merge-l-chunk-end",
+ insert: "CodeMirror-merge-l-inserted",
+ del: "CodeMirror-merge-l-deleted",
+ connect: "CodeMirror-merge-l-connect"}
+ : {chunk: "CodeMirror-merge-r-chunk",
+ start: "CodeMirror-merge-r-chunk-start",
+ end: "CodeMirror-merge-r-chunk-end",
+ insert: "CodeMirror-merge-r-inserted",
+ del: "CodeMirror-merge-r-deleted",
+ connect: "CodeMirror-merge-r-connect"};
}
DiffView.prototype = {
@@ -31,9 +32,17 @@
this.diff = getDiff(orig, options.value);
this.diffOutOfDate = false;
+ this.showDifferences = options.showDifferences !== false;
this.forceUpdate = registerUpdate(this);
setScrollLock(this, true, false);
registerScroll(this);
+ },
+ setShowDifferences: function(val) {
+ val = val !== false;
+ if (val != this.showDifferences) {
+ this.showDifferences = val;
+ this.forceUpdate("full");
+ }
}
};
@@ -41,26 +50,38 @@
var edit = {from: 0, to: 0, marked: []};
var orig = {from: 0, to: 0, marked: []};
var debounceChange;
- function update() {
+ function update(mode) {
+ if (mode == "full") {
+ if (dv.svg) clear(dv.svg);
+ clear(dv.copyButtons);
+ clearMarks(dv.edit, edit.marked, dv.classes);
+ clearMarks(dv.orig, orig.marked, dv.classes);
+ edit.from = edit.to = orig.from = orig.to = 0;
+ }
if (dv.diffOutOfDate) {
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
dv.diffOutOfDate = false;
+ CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
+ }
+ if (dv.showDifferences) {
+ updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
+ updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
}
- updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
- updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
drawConnectors(dv);
}
function set(slow) {
clearTimeout(debounceChange);
debounceChange = setTimeout(update, slow == true ? 250 : 100);
}
- dv.edit.on("change", function() {
+ function change() {
if (!dv.diffOutOfDate) {
dv.diffOutOfDate = true;
edit.from = edit.to = orig.from = orig.to = 0;
}
set(true);
- });
+ }
+ dv.edit.on("change", change);
+ dv.orig.on("change", change);
dv.edit.on("viewportChange", set);
dv.orig.on("viewportChange", set);
update();
@@ -93,7 +114,21 @@
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
var ratio = (midY - off.top) / (off.bot - off.top);
- other.scrollTo(null, (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top));
+ var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);
+
+ var botDist, mix;
+ // Some careful tweaking to make sure no space is left out of view
+ // when scrolling to top or bottom.
+ if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {
+ targetPos = targetPos * mix + sInfo.top * (1 - mix);
+ } else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {
+ var otherInfo = other.getScrollInfo();
+ var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;
+ if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)
+ targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);
+ }
+
+ other.scrollTo(sInfo.left, targetPos);
other.state.scrollSetAt = now;
other.state.scrollSetBy = dv;
return true;
@@ -197,6 +232,8 @@
// Updating the gap between editor and original
function drawConnectors(dv) {
+ if (!dv.showDifferences) return;
+
if (dv.svg) {
clear(dv.svg);
var w = dv.gap.offsetWidth;
@@ -208,8 +245,8 @@
var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
iterateChunks(dv.diff, function(topOrig, botOrig, topEdit, botEdit) {
- if (topEdit >= vpEdit.to || botEdit < vpEdit.from ||
- topOrig >= vpOrig.to || botOrig < vpOrig.from)
+ if (topEdit > vpEdit.to || botEdit < vpEdit.from ||
+ topOrig > vpOrig.to || botOrig < vpOrig.from)
return;
var topLpx = dv.orig.heightAtLine(topOrig, "local") - sTopOrig, top = topLpx;
if (dv.svg) {
@@ -225,7 +262,7 @@
"class", dv.classes.connect);
}
var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
- "CodeMirror-diff-copy"));
+ "CodeMirror-merge-copy"));
copy.title = "Revert chunk";
copy.chunk = {topEdit: topEdit, botEdit: botEdit, topOrig: topOrig, botOrig: botOrig};
copy.style.top = top + "px";
@@ -250,23 +287,25 @@
if (hasLeft) {
left = this.left = new DiffView(this, "left");
- var leftPane = elt("div", null, "CodeMirror-diff-pane");
+ var leftPane = elt("div", null, "CodeMirror-merge-pane");
wrap.push(leftPane);
wrap.push(buildGap(left));
}
- var editPane = elt("div", null, "CodeMirror-diff-pane");
+ var editPane = elt("div", null, "CodeMirror-merge-pane");
wrap.push(editPane);
if (hasRight) {
right = this.right = new DiffView(this, "right");
wrap.push(buildGap(right));
- var rightPane = elt("div", null, "CodeMirror-diff-pane");
+ var rightPane = elt("div", null, "CodeMirror-merge-pane");
wrap.push(rightPane);
}
+ (hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";
+
wrap.push(elt("div", null, null, "height: 0; clear: both;"));
- var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-diff CodeMirror-diff-" + panes + "pane"));
+ var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));
this.edit = CodeMirror(editPane, copyObj(options));
if (left) left.init(leftPane, origLeft, options);
@@ -284,11 +323,11 @@
};
function buildGap(dv) {
- var lock = dv.lockButton = elt("div", null, "CodeMirror-diff-scrolllock");
+ var lock = dv.lockButton = elt("div", null, "CodeMirror-merge-scrolllock");
lock.title = "Toggle locked scrolling";
- var lockWrap = elt("div", [lock], "CodeMirror-diff-scrolllock-wrap");
+ var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");
CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
- dv.copyButtons = elt("div", null, "CodeMirror-diff-copybuttons-" + dv.type);
+ dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);
CodeMirror.on(dv.copyButtons, "click", function(e) {
var node = e.target || e.srcElement;
if (node.chunk) copyChunk(dv, node.chunk);
@@ -299,14 +338,18 @@
dv.svg = svg;
if (svg) gapElts.push(svg);
- return dv.gap = elt("div", gapElts, "CodeMirror-diff-gap");
+ return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap");
}
MergeView.prototype = {
constuctor: MergeView,
editor: function() { return this.edit; },
rightOriginal: function() { return this.right && this.right.orig; },
- leftOriginal: function() { return this.left && this.left.orig; }
+ leftOriginal: function() { return this.left && this.left.orig; },
+ setShowDifferences: function(val) {
+ if (this.right) this.right.setShowDifferences(val);
+ if (this.left) this.left.setShowDifferences(val);
+ }
};
// Operations on diffs
diff --git a/applications/admin/static/codemirror/addon/runmode/runmode-standalone.js b/applications/admin/static/codemirror/addon/runmode/runmode-standalone.js
index 7a9b82ff..d117166c 100644
--- a/applications/admin/static/codemirror/addon/runmode/runmode-standalone.js
+++ b/applications/admin/static/codemirror/addon/runmode/runmode-standalone.js
@@ -2,6 +2,9 @@
window.CodeMirror = {};
+(function() {
+"use strict";
+
function splitLines(string){ return string.split(/\r?\n|\r/); };
function StringStream(string) {
@@ -43,12 +46,14 @@ StringStream.prototype = {
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) {
+ var substr = this.string.substr(this.pos, pattern.length);
+ if (cased(substr) == cased(pattern)) {
if (consume !== false) this.pos += pattern.length;
return true;
}
} else {
var match = this.string.slice(this.pos).match(pattern);
+ if (match && match.index > 0) return null;
if (match && consume !== false) this.pos += match[0].length;
return match;
}
@@ -123,8 +128,9 @@ CodeMirror.runMode = function (string, modespec, callback, options) {
var stream = new CodeMirror.StringStream(lines[i]);
while (!stream.eol()) {
var style = mode.token(stream, state);
- callback(stream.current(), style, i, stream.start);
+ callback(stream.current(), style, i, stream.start, state);
stream.start = stream.pos;
}
}
};
+})();
diff --git a/applications/admin/static/codemirror/addon/runmode/runmode.js b/applications/admin/static/codemirror/addon/runmode/runmode.js
index a7da6d71..7aafa2ad 100644
--- a/applications/admin/static/codemirror/addon/runmode/runmode.js
+++ b/applications/admin/static/codemirror/addon/runmode/runmode.js
@@ -49,7 +49,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
var stream = new CodeMirror.StringStream(lines[i]);
while (!stream.eol()) {
var style = mode.token(stream, state);
- callback(stream.current(), style, i, stream.start);
+ callback(stream.current(), style, i, stream.start, state);
stream.start = stream.pos;
}
}
diff --git a/applications/admin/static/codemirror/addon/runmode/runmode.node.js b/applications/admin/static/codemirror/addon/runmode/runmode.node.js
index a6ea919d..0f1088fa 100644
--- a/applications/admin/static/codemirror/addon/runmode/runmode.node.js
+++ b/applications/admin/static/codemirror/addon/runmode/runmode.node.js
@@ -41,12 +41,14 @@ StringStream.prototype = {
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) {
+ var substr = this.string.substr(this.pos, pattern.length);
+ if (cased(substr) == cased(pattern)) {
if (consume !== false) this.pos += pattern.length;
return true;
}
} else {
var match = this.string.slice(this.pos).match(pattern);
+ if (match && match.index > 0) return null;
if (match && consume !== false) this.pos += match[0].length;
return match;
}
@@ -94,7 +96,7 @@ exports.runMode = function(string, modespec, callback) {
var stream = new exports.StringStream(lines[i]);
while (!stream.eol()) {
var style = mode.token(stream, state);
- callback(stream.current(), style, i, stream.start);
+ callback(stream.current(), style, i, stream.start, state);
stream.start = stream.pos;
}
}
diff --git a/applications/admin/static/codemirror/addon/search/match-highlighter.js b/applications/admin/static/codemirror/addon/search/match-highlighter.js
index 21216758..e5cbeaca 100644
--- a/applications/admin/static/codemirror/addon/search/match-highlighter.js
+++ b/applications/admin/static/codemirror/addon/search/match-highlighter.js
@@ -15,15 +15,18 @@
(function() {
var DEFAULT_MIN_CHARS = 2;
var DEFAULT_TOKEN_STYLE = "matchhighlight";
+ var DEFAULT_DELAY = 100;
function State(options) {
if (typeof options == "object") {
this.minChars = options.minChars;
this.style = options.style;
this.showToken = options.showToken;
+ this.delay = options.delay;
}
if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;
if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;
+ if (this.delay == null) this.delay = DEFAULT_DELAY;
this.overlay = this.timeout = null;
}
@@ -45,7 +48,7 @@
function cursorActivity(cm) {
var state = cm.state.matchHighlighter;
clearTimeout(state.timeout);
- state.timeout = setTimeout(function() {highlightMatches(cm);}, 100);
+ state.timeout = setTimeout(function() {highlightMatches(cm);}, state.delay);
}
function highlightMatches(cm) {
@@ -55,11 +58,13 @@
cm.removeOverlay(state.overlay);
state.overlay = null;
}
-
if (!cm.somethingSelected() && state.showToken) {
- var tok = cm.getTokenAt(cm.getCursor()).string;
- if (/\w/.test(tok))
- cm.addOverlay(state.overlay = makeOverlay(tok, true, state.style));
+ var re = state.showToken === true ? /[\w$]/ : state.showToken;
+ var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
+ while (start && re.test(line.charAt(start - 1))) --start;
+ while (end < line.length && re.test(line.charAt(end))) ++end;
+ if (start < end)
+ cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style));
return;
}
if (cm.getCursor("head").line != cm.getCursor("anchor").line) return;
@@ -69,15 +74,15 @@
});
}
- function boundariesAround(stream) {
- return (stream.start || /.\b./.test(stream.string.slice(stream.start - 1, stream.start + 1))) &&
- (stream.pos == stream.string.length || /.\b./.test(stream.string.slice(stream.pos - 1, stream.pos + 1)));
+ function boundariesAround(stream, re) {
+ return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&
+ (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
}
- function makeOverlay(query, wordBoundaries, style) {
+ function makeOverlay(query, hasBoundary, style) {
return {token: function(stream) {
if (stream.match(query) &&
- (!wordBoundaries || boundariesAround(stream)))
+ (!hasBoundary || boundariesAround(stream, hasBoundary)))
return style;
stream.next();
stream.skipTo(query.charAt(0)) || stream.skipToEnd();
diff --git a/applications/admin/static/codemirror/addon/search/searchcursor.js b/applications/admin/static/codemirror/addon/search/searchcursor.js
index 3da3f04e..c034d586 100644
--- a/applications/admin/static/codemirror/addon/search/searchcursor.js
+++ b/applications/admin/static/codemirror/addon/search/searchcursor.js
@@ -69,8 +69,8 @@
this.matches = function(reverse, pos) {
var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(doc.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)
+ if (reverse ? offsetA > pos.ch || offsetA != match.length
+ : offsetA < pos.ch || offsetA != line.length - match.length)
return;
for (;;) {
if (reverse ? !ln : ln == doc.lineCount() - 1) return;
diff --git a/applications/admin/static/codemirror/addon/selection/active-line.js b/applications/admin/static/codemirror/addon/selection/active-line.js
index 65fab6f1..e5050865 100644
--- a/applications/admin/static/codemirror/addon/selection/active-line.js
+++ b/applications/admin/static/codemirror/addon/selection/active-line.js
@@ -29,7 +29,7 @@
}
function updateActiveLine(cm) {
- var line = cm.getLineHandle(cm.getCursor().line);
+ var line = cm.getLineHandleVisualStart(cm.getCursor().line);
if (cm.state.activeLine == line) return;
clearActiveLine(cm);
cm.addLineClass(line, "wrap", WRAP_CLASS);
diff --git a/applications/admin/static/codemirror/bin/lint b/applications/admin/static/codemirror/bin/lint
index bbb85b6c..4f70994c 100755
--- a/applications/admin/static/codemirror/bin/lint
+++ b/applications/admin/static/codemirror/bin/lint
@@ -1,11 +1,12 @@
#!/usr/bin/env node
-var lint = require("../test/lint/lint");
+var lint = require("../test/lint/lint"),
+ path = require("path");
if (process.argv.length > 2) {
lint.checkDir(process.argv[2]);
} else {
- process.chdir(__dirname.slice(0, __dirname.lastIndexOf("/")));
+ process.chdir(path.resolve(__dirname, ".."));
lint.checkDir("lib");
lint.checkDir("mode");
lint.checkDir("addon");
diff --git a/applications/admin/static/codemirror/keymap/emacs.js b/applications/admin/static/codemirror/keymap/emacs.js
index 8727121c..7a3dfb11 100644
--- a/applications/admin/static/codemirror/keymap/emacs.js
+++ b/applications/admin/static/codemirror/keymap/emacs.js
@@ -353,7 +353,7 @@
},
"Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": repeated("undo"), "K": "close",
- "Delete": function(cm) { kill(cm, cm.getCursor(), sentenceEnd(cm, 1), true); },
+ "Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
auto: "emacs", nofallthrough: true, disableInput: true
};
diff --git a/applications/admin/static/codemirror/keymap/vim.js b/applications/admin/static/codemirror/keymap/vim.js
index e05be031..9ad17af3 100644
--- a/applications/admin/static/codemirror/keymap/vim.js
+++ b/applications/admin/static/codemirror/keymap/vim.js
@@ -40,6 +40,10 @@
* TODO: Implement the remaining special marks. They have more complex
* behavior.
*
+ * Events:
+ * 'vim-mode-change' - raised on the editor anytime the current mode changes,
+ * Event object: {mode: "visual", subMode: "linewise"}
+ *
* Code structure:
* 1. Default keymap
* 2. Variable declarations and short basic helpers
@@ -206,8 +210,7 @@
// Operators
{ keys: ['d'], type: 'operator', operator: 'delete' },
{ keys: ['y'], type: 'operator', operator: 'yank' },
- { keys: ['c'], type: 'operator', operator: 'change',
- operatorArgs: { enterInsertMode: true } },
+ { keys: ['c'], type: 'operator', operator: 'change' },
{ keys: ['>'], type: 'operator', operator: 'indent',
operatorArgs: { indentRight: true }},
{ keys: ['<'], type: 'operator', operator: 'indent',
@@ -231,10 +234,11 @@
motion: 'moveToEol', motionArgs: { inclusive: true },
operatorMotionArgs: { visualLine: true }},
{ keys: ['C'], type: 'operatorMotion',
- operator: 'change', operatorArgs: { enterInsertMode: true },
+ operator: 'change',
motion: 'moveToEol', motionArgs: { inclusive: true },
operatorMotionArgs: { visualLine: true }},
- { keys: ['~'], type: 'operatorMotion', operator: 'swapcase',
+ { keys: ['~'], type: 'operatorMotion',
+ operator: 'swapcase', operatorArgs: { shouldMoveCursor: true },
motion: 'moveByCharacters', motionArgs: { forward: true }},
// Actions
{ keys: [''], type: 'action', action: 'jumpListWalk',
@@ -315,6 +319,28 @@
];
var Vim = function() {
+ CodeMirror.defineOption('vimMode', false, function(cm, val) {
+ if (val) {
+ cm.setOption('keyMap', 'vim');
+ CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
+ cm.on('beforeSelectionChange', beforeSelectionChange);
+ maybeInitVimState(cm);
+ } else if (cm.state.vim) {
+ cm.setOption('keyMap', 'default');
+ cm.off('beforeSelectionChange', beforeSelectionChange);
+ cm.state.vim = null;
+ }
+ });
+ function beforeSelectionChange(cm, cur) {
+ var vim = cm.state.vim;
+ if (vim.insertMode || vim.exMode) return;
+
+ var head = cur.head;
+ if (head.ch && head.ch == cm.doc.getLine(head.line).length) {
+ head.ch--;
+ }
+ }
+
var numberRegex = /[\d]/;
var wordRegexp = [(/\w/), (/[^\w\s]/)], bigWordRegexp = [(/\S/)];
function makeKeyRange(start, size) {
@@ -450,28 +476,11 @@
};
};
- // Global Vim state. Call getVimGlobalState to get and initialize.
- var vimGlobalState;
- function getVimGlobalState() {
- if (!vimGlobalState) {
- vimGlobalState = {
- // The current search query.
- searchQuery: null,
- // Whether we are searching backwards.
- searchIsReversed: false,
- jumpList: createCircularJumpList(),
- macroModeState: createMacroState(),
- // Recording latest f, t, F or T motion command.
- lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''},
- registerController: new RegisterController({})
- };
- }
- return vimGlobalState;
- }
- function getVimState(cm) {
- if (!cm.vimState) {
+
+ function maybeInitVimState(cm) {
+ if (!cm.state.vim) {
// Store instance state in the CodeMirror object.
- cm.vimState = {
+ cm.state.vim = {
inputState: new InputState(),
// Vim's input state that triggered the last edit, used to repeat
// motions and operators with '.'.
@@ -500,7 +509,21 @@
visualLine: false
};
}
- return cm.vimState;
+ return cm.state.vim;
+ }
+ var vimGlobalState;
+ function resetVimGlobalState() {
+ vimGlobalState = {
+ // The current search query.
+ searchQuery: null,
+ // Whether we are searching backwards.
+ searchIsReversed: false,
+ jumpList: createCircularJumpList(),
+ macroModeState: createMacroState(),
+ // Recording latest f, t, F or T motion command.
+ lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''},
+ registerController: new RegisterController({})
+ };
}
var vimApi= {
@@ -510,16 +533,19 @@
// Testing hook, though it might be useful to expose the register
// controller anyways.
getRegisterController: function() {
- return getVimGlobalState().registerController;
+ return vimGlobalState.registerController;
},
// Testing hook.
- clearVimGlobalState_: function() {
- vimGlobalState = null;
- },
+ resetVimGlobalState_: resetVimGlobalState,
+
// Testing hook.
getVimGlobalState_: function() {
return vimGlobalState;
},
+
+ // Testing hook.
+ maybeInitVimState_: maybeInitVimState,
+
InsertModeKey: InsertModeKey,
map: function(lhs, rhs) {
// Add user defined key bindings.
@@ -532,17 +558,12 @@
exCommands[name]=func;
exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'};
},
- // Initializes vim state variable on the CodeMirror object. Should only be
- // called lazily by handleKey or for testing.
- maybeInitState: function(cm) {
- getVimState(cm);
- },
// This is the outermost function called by CodeMirror, after keys have
// been mapped to their Vim equivalents.
handleKey: function(cm, key) {
var command;
- var vim = getVimState(cm);
- var macroModeState = getVimGlobalState().macroModeState;
+ var vim = maybeInitVimState(cm);
+ var macroModeState = vimGlobalState.macroModeState;
if (macroModeState.enteredMacroMode) {
if (key == 'q') {
actions.exitMacroRecordMode();
@@ -554,19 +575,17 @@
// Clear input state and get back to normal mode.
vim.inputState = new InputState();
if (vim.visualMode) {
- exitVisualMode(cm, vim);
+ exitVisualMode(cm);
}
return;
}
- if (vim.visualMode &&
- cursorEqual(cm.getCursor('head'), cm.getCursor('anchor'))) {
- // The selection was cleared. Exit visual mode.
- exitVisualMode(cm, vim);
- }
+ // Enter visual mode when the mouse selects text.
if (!vim.visualMode &&
!cursorEqual(cm.getCursor('head'), cm.getCursor('anchor'))) {
vim.visualMode = true;
vim.visualLine = false;
+ CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"});
+ cm.on('mousedown', exitVisualMode);
}
if (key != '0' || (key == '0' && vim.inputState.getRepeat() === 0)) {
// Have to special case 0 since it's both a motion and a number.
@@ -970,7 +989,7 @@
// cachedCursor is used to save the old position of the cursor
// when * or # causes vim to seek for the nearest word and shift
// the cursor before entering the motion.
- getVimGlobalState().jumpList.cachedCursor = cm.getCursor();
+ vimGlobalState.jumpList.cachedCursor = cm.getCursor();
cm.setCursor(word.start);
handleQuery(query, true /** ignoreCase */, false /** smartCase */);
@@ -1052,7 +1071,7 @@
return;
}
if (motionArgs.toJumplist) {
- var jumpList = getVimGlobalState().jumpList;
+ var jumpList = vimGlobalState.jumpList;
// if the current motion is # or *, use cachedCursor
var cachedCursor = jumpList.cachedCursor;
if (cachedCursor) {
@@ -1091,6 +1110,11 @@
if (vim.visualLine) {
if (cursorIsBefore(selectionStart, selectionEnd)) {
selectionStart.ch = 0;
+
+ var lastLine = cm.lastLine();
+ if (selectionEnd.line > lastLine) {
+ selectionEnd.line = lastLine;
+ }
selectionEnd.ch = lineLength(cm, selectionEnd.line);
} else {
selectionEnd.ch = 0;
@@ -1146,15 +1170,12 @@
operators[operator](cm, operatorArgs, vim, curStart,
curEnd, curOriginal);
if (vim.visualMode) {
- exitVisualMode(cm, vim);
- }
- if (operatorArgs.enterInsertMode) {
- actions.enterInsertMode(cm, {}, vim);
+ exitVisualMode(cm);
}
}
},
recordLastEdit: function(vim, inputState, actionCommand) {
- var macroModeState = getVimGlobalState().macroModeState;
+ var macroModeState = vimGlobalState.macroModeState;
if (macroModeState.inReplay) { return; }
vim.lastEditInputState = inputState;
vim.lastEditActionCommand = actionCommand;
@@ -1272,8 +1293,13 @@
}
var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0);
var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat;
- if (line < cm.firstLine() || line > cm.lastLine() ) {
- return null;
+ var first = cm.firstLine();
+ var last = cm.lastLine();
+ // Vim cancels linewise motions that start on an edge and move beyond
+ // that edge. It does not cancel motions that do not start on an edge.
+ if ((line < first && cur.line == first) ||
+ (line > last && cur.line == last)) {
+ return;
}
if(motionArgs.toFirstChar){
endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line));
@@ -1456,7 +1482,7 @@
return [start, end];
},
repeatLastCharacterSearch: function(cm, motionArgs) {
- var lastSearch = getVimGlobalState().lastChararacterSearch;
+ var lastSearch = vimGlobalState.lastChararacterSearch;
var repeat = motionArgs.repeat;
var forward = motionArgs.forward === lastSearch.forward;
var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1);
@@ -1474,22 +1500,16 @@
var operators = {
change: function(cm, operatorArgs, _vim, curStart, curEnd) {
- getVimGlobalState().registerController.pushText(
+ vimGlobalState.registerController.pushText(
operatorArgs.registerName, 'change', cm.getRange(curStart, curEnd),
operatorArgs.linewise);
if (operatorArgs.linewise) {
- // Delete starting at the first nonwhitespace character of the first
- // line, instead of from the start of the first line. This way we get
- // an indent when we get into insert mode. This behavior isn't quite
- // correct because we should treat this as a completely new line, and
- // indent should be whatever codemirror thinks is the right indent.
- // But cm.indentLine doesn't seem work on empty lines.
- // TODO: Fix the above.
- curStart.ch =
- findFirstNonWhiteSpaceCharacter(cm.getLine(curStart.line));
- // Insert an additional newline so that insert mode can start there.
- // curEnd should be on the first character of the new line.
- cm.replaceRange('\n', curStart, curEnd);
+ // Push the next line back down, if there is a next line.
+ var replacement = curEnd.line > cm.lastLine() ? '' : '\n';
+ cm.replaceRange(replacement, curStart, curEnd);
+ cm.indentLine(curStart.line, 'smart');
+ // null ch so setCursor moves to end of line.
+ curStart.ch = null;
} else {
// Exclude trailing whitespace if the range is not all whitespace.
var text = cm.getRange(curStart, curEnd);
@@ -1501,6 +1521,7 @@
}
cm.replaceRange('', curStart, curEnd);
}
+ actions.enterInsertMode(cm, {}, cm.state.vim);
cm.setCursor(curStart);
},
// delete is a javascript keyword.
@@ -1512,7 +1533,7 @@
curStart.line--;
curStart.ch = lineLength(cm, curStart.line);
}
- getVimGlobalState().registerController.pushText(
+ vimGlobalState.registerController.pushText(
operatorArgs.registerName, 'delete', cm.getRange(curStart, curEnd),
operatorArgs.linewise);
cm.replaceRange('', curStart, curEnd);
@@ -1542,7 +1563,7 @@
cm.setCursor(curStart);
cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm));
},
- swapcase: function(cm, _operatorArgs, _vim, curStart, curEnd, curOriginal) {
+ swapcase: function(cm, operatorArgs, _vim, curStart, curEnd, curOriginal) {
var toSwap = cm.getRange(curStart, curEnd);
var swapped = '';
for (var i = 0; i < toSwap.length; i++) {
@@ -1551,10 +1572,12 @@
character.toUpperCase();
}
cm.replaceRange(swapped, curStart, curEnd);
- cm.setCursor(curOriginal);
+ if (!operatorArgs.shouldMoveCursor) {
+ cm.setCursor(curOriginal);
+ }
},
yank: function(cm, operatorArgs, _vim, curStart, curEnd, curOriginal) {
- getVimGlobalState().registerController.pushText(
+ vimGlobalState.registerController.pushText(
operatorArgs.registerName, 'yank',
cm.getRange(curStart, curEnd), operatorArgs.linewise);
cm.setCursor(curOriginal);
@@ -1568,7 +1591,7 @@
}
var repeat = actionArgs.repeat;
var forward = actionArgs.forward;
- var jumpList = getVimGlobalState().jumpList;
+ var jumpList = vimGlobalState.jumpList;
var mark = jumpList.move(cm, forward ? repeat : -repeat);
var markPos = mark ? mark.find() : undefined;
@@ -1594,7 +1617,7 @@
replayMacro: function(cm, actionArgs) {
var registerName = actionArgs.selectedCharacter;
var repeat = actionArgs.repeat;
- var macroModeState = getVimGlobalState().macroModeState;
+ var macroModeState = vimGlobalState.macroModeState;
if (registerName == '@') {
registerName = macroModeState.latestRegister;
}
@@ -1604,18 +1627,19 @@
}
},
exitMacroRecordMode: function() {
- var macroModeState = getVimGlobalState().macroModeState;
+ var macroModeState = vimGlobalState.macroModeState;
macroModeState.toggle();
parseKeyBufferToRegister(macroModeState.latestRegister,
macroModeState.macroKeyBuffer);
},
enterMacroRecordMode: function(cm, actionArgs) {
- var macroModeState = getVimGlobalState().macroModeState;
+ var macroModeState = vimGlobalState.macroModeState;
var registerName = actionArgs.selectedCharacter;
macroModeState.toggle(cm, registerName);
emptyMacroKeyBuffer(macroModeState);
},
enterInsertMode: function(cm, actionArgs, vim) {
+ if (cm.getOption('readOnly')) { return; }
vim.insertMode = true;
vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1;
var insertAt = (actionArgs) ? actionArgs.insertAt : null;
@@ -1633,10 +1657,12 @@
// Handle Replace-mode as a special case of insert mode.
cm.toggleOverwrite(true);
cm.setOption('keyMap', 'vim-replace');
+ CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"});
} else {
cm.setOption('keyMap', 'vim-insert');
+ CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"});
}
- if (!getVimGlobalState().macroModeState.inReplay) {
+ if (!vimGlobalState.macroModeState.inReplay) {
// Only record if not replaying.
cm.on('change', onChange);
cm.on('cursorActivity', onCursorActivity);
@@ -1651,6 +1677,7 @@
// equal to the repeat times the size of the previous visual
// operation.
if (!vim.visualMode) {
+ cm.on('mousedown', exitVisualMode);
vim.visualMode = true;
vim.visualLine = !!actionArgs.linewise;
if (vim.visualLine) {
@@ -1675,6 +1702,7 @@
} else {
cm.setSelection(curStart, curEnd);
}
+ CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : ""});
} else {
curStart = cm.getCursor('anchor');
curEnd = cm.getCursor('head');
@@ -1687,12 +1715,14 @@
curEnd.ch = cursorIsBefore(curStart, curEnd) ?
lineLength(cm, curEnd.line) : 0;
cm.setSelection(curStart, curEnd);
+ CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: "linewise"});
} else if (vim.visualLine && !actionArgs.linewise) {
// v pressed in linewise visual mode. Switch to characterwise visual
// mode instead of exiting visual mode.
vim.visualLine = false;
+ CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"});
} else {
- exitVisualMode(cm, vim);
+ exitVisualMode(cm);
}
}
updateMark(cm, vim, '<', cursorIsBefore(curStart, curEnd) ? curStart
@@ -1728,6 +1758,7 @@
});
},
newLineAndEnterInsertMode: function(cm, actionArgs, vim) {
+ vim.insertMode = true;
var insertAt = cm.getCursor();
if (insertAt.line === cm.firstLine() && !actionArgs.after) {
// Special case for inserting newline before start of document.
@@ -1746,7 +1777,7 @@
},
paste: function(cm, actionArgs) {
var cur = cm.getCursor();
- var register = getVimGlobalState().registerController.getRegister(
+ var register = vimGlobalState.registerController.getRegister(
actionArgs.registerName);
if (!register.text) {
return;
@@ -1832,7 +1863,7 @@
cm.replaceRange(replaceWithStr, curStart, curEnd);
if(vim.visualMode){
cm.setCursor(curStart);
- exitVisualMode(cm,vim);
+ exitVisualMode(cm);
}else{
cm.setCursor(offsetCursor(curEnd, 0, -1));
}
@@ -1989,7 +2020,9 @@
return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1');
}
- function exitVisualMode(cm, vim) {
+ function exitVisualMode(cm) {
+ cm.off('mousedown', exitVisualMode);
+ var vim = cm.state.vim;
vim.visualMode = false;
vim.visualLine = false;
var selectionStart = cm.getCursor('anchor');
@@ -2000,6 +2033,7 @@
// it's not supposed to be.
cm.setCursor(clipCursorToContent(cm, selectionEnd));
}
+ CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
}
// Remove any trailing newlines from the selection. For
@@ -2113,12 +2147,11 @@
function recordJumpPosition(cm, oldCur, newCur) {
if(!cursorEqual(oldCur, newCur)) {
- getVimGlobalState().jumpList.add(cm, oldCur, newCur);
+ vimGlobalState.jumpList.add(cm, oldCur, newCur);
}
}
function recordLastCharacterSearch(increment, args) {
- var vimGlobalState = getVimGlobalState();
vimGlobalState.lastChararacterSearch.increment = increment;
vimGlobalState.lastChararacterSearch.forward = args.forward;
vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter;
@@ -2572,10 +2605,10 @@
function SearchState() {}
SearchState.prototype = {
getQuery: function() {
- return getVimGlobalState().query;
+ return vimGlobalState.query;
},
setQuery: function(query) {
- getVimGlobalState().query = query;
+ vimGlobalState.query = query;
},
getOverlay: function() {
return this.searchOverlay;
@@ -2584,14 +2617,14 @@
this.searchOverlay = overlay;
},
isReversed: function() {
- return getVimGlobalState().isReversed;
+ return vimGlobalState.isReversed;
},
setReversed: function(reversed) {
- getVimGlobalState().isReversed = reversed;
+ vimGlobalState.isReversed = reversed;
}
};
function getSearchState(cm) {
- var vim = getVimState(cm);
+ var vim = cm.state.vim;
return vim.searchState_ || (vim.searchState_ = new SearchState());
}
function dialog(cm, template, shortText, onClose, options) {
@@ -2840,9 +2873,9 @@
};
Vim.ExCommandDispatcher.prototype = {
processCommand: function(cm, input) {
- var vim = getVimState(cm);
+ var vim = cm.state.vim;
if (vim.visualMode) {
- exitVisualMode(cm, vim);
+ exitVisualMode(cm);
}
var inputStream = new CodeMirror.StringStream(input);
var params = {};
@@ -2921,7 +2954,7 @@
case '$':
return cm.lastLine();
case '\'':
- var mark = getVimState(cm).marks[inputStream.next()];
+ var mark = cm.state.vim.marks[inputStream.next()];
if (mark && mark.find()) {
return mark.find().line;
}
@@ -3031,7 +3064,7 @@
exCommandDispatcher.map(mapArgs[0], mapArgs[1], cm);
},
move: function(cm, params) {
- commandDispatcher.processCommand(cm, getVimState(cm), {
+ commandDispatcher.processCommand(cm, cm.state.vim, {
type: 'motion',
motion: 'moveToLineOrEdgeOfDocument',
motionArgs: { forward: false, explicitRepeat: true,
@@ -3186,7 +3219,7 @@
return;
}
- var state = getVimState(cm);
+ var state = cm.state.vim;
var stream = new CodeMirror.StringStream(params.argString.trim());
while (!stream.eol()) {
stream.eatSpace();
@@ -3257,6 +3290,7 @@
function doReplace(cm, confirm, lineStart, lineEnd, searchCursor, query,
replaceWith) {
// Set up all the functions.
+ cm.state.vim.exMode = true;
var done = false;
var lastPos = searchCursor.from();
function replaceAll() {
@@ -3291,7 +3325,8 @@
cm.focus();
if (lastPos) {
cm.setCursor(lastPos);
- var vim = getVimState(cm);
+ var vim = cm.state.vim;
+ vim.exMode = false;
vim.lastHPos = vim.lastHSPos = lastPos.ch;
}
}
@@ -3403,9 +3438,8 @@
CodeMirror.keyMap.vim = buildVimKeyMap();
function exitInsertMode(cm) {
- var vim = getVimState(cm);
- vim.insertMode = false;
- var inReplay = getVimGlobalState().macroModeState.inReplay;
+ var vim = cm.state.vim;
+ var inReplay = vimGlobalState.macroModeState.inReplay;
if (!inReplay) {
cm.off('change', onChange);
cm.off('cursorActivity', onCursorActivity);
@@ -3419,8 +3453,10 @@
}
delete vim.insertModeRepeat;
cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
+ vim.insertMode = false;
cm.setOption('keyMap', 'vim');
cm.toggleOverwrite(false); // exit replace mode if we were in it.
+ CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
}
CodeMirror.keyMap['vim-insert'] = {
@@ -3446,7 +3482,7 @@
function parseRegisterToKeyBuffer(macroModeState, registerName) {
var match, key;
- var register = getVimGlobalState().registerController.getRegister(registerName);
+ var register = vimGlobalState.registerController.getRegister(registerName);
var text = register.toString();
var macroKeyBuffer = macroModeState.macroKeyBuffer;
emptyMacroKeyBuffer(macroModeState);
@@ -3462,7 +3498,7 @@
function parseKeyBufferToRegister(registerName, keyBuffer) {
var text = keyBuffer.join('');
- getVimGlobalState().registerController.setRegisterText(registerName, text);
+ vimGlobalState.registerController.setRegisterText(registerName, text);
}
function emptyMacroKeyBuffer(macroModeState) {
@@ -3490,7 +3526,7 @@
* Should only be active in insert mode.
*/
function onChange(_cm, changeObj) {
- var macroModeState = getVimGlobalState().macroModeState;
+ var macroModeState = vimGlobalState.macroModeState;
var lastChange = macroModeState.lastInsertModeChanges;
while (changeObj) {
lastChange.expectCursorActivityForChange = true;
@@ -3510,7 +3546,7 @@
* - Should only be active in insert mode.
*/
function onCursorActivity() {
- var macroModeState = getVimGlobalState().macroModeState;
+ var macroModeState = vimGlobalState.macroModeState;
var lastChange = macroModeState.lastInsertModeChanges;
if (lastChange.expectCursorActivityForChange) {
lastChange.expectCursorActivityForChange = false;
@@ -3531,7 +3567,7 @@
* - For recording deletes in insert mode.
*/
function onKeyEventTargetKeyDown(e) {
- var macroModeState = getVimGlobalState().macroModeState;
+ var macroModeState = vimGlobalState.macroModeState;
var lastChange = macroModeState.lastInsertModeChanges;
var keyName = CodeMirror.keyName(e);
function onKeyFound() {
@@ -3553,7 +3589,7 @@
* corresponding enterInsertMode call was made with a count.
*/
function repeatLastEdit(cm, vim, repeat, repeatForInsert) {
- var macroModeState = getVimGlobalState().macroModeState;
+ var macroModeState = vimGlobalState.macroModeState;
macroModeState.inReplay = true;
var isAction = !!vim.lastEditActionCommand;
var cachedInputState = vim.inputState;
@@ -3621,6 +3657,7 @@
}
}
+ resetVimGlobalState();
return vimApi;
};
// Initialize Vim and make it available as an API.
diff --git a/applications/admin/static/codemirror/lib/codemirror.css b/applications/admin/static/codemirror/lib/codemirror.css
index 52881f7d..4e300b2b 100644
--- a/applications/admin/static/codemirror/lib/codemirror.css
+++ b/applications/admin/static/codemirror/lib/codemirror.css
@@ -95,6 +95,7 @@
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
+.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
@@ -117,6 +118,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
}
.CodeMirror-sizer {
position: relative;
@@ -155,6 +158,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
padding-bottom: 30px;
margin-bottom: -32px;
display: inline-block;
@@ -192,6 +197,16 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
white-space: pre-wrap;
word-break: normal;
}
+.CodeMirror-code pre {
+ border-right: 30px solid transparent;
+ width: -webkit-fit-content;
+ width: -moz-fit-content;
+ width: fit-content;
+}
+.CodeMirror-wrap .CodeMirror-code pre {
+ border-right: none;
+ width: auto;
+}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
@@ -204,8 +219,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
overflow: auto;
}
-.CodeMirror-widget {
-}
+.CodeMirror-widget {}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;
@@ -213,7 +227,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-measure {
position: absolute;
- width: 100%; height: 0px;
+ width: 100%;
+ height: 0;
overflow: hidden;
visibility: hidden;
}
diff --git a/applications/admin/static/codemirror/lib/codemirror.js b/applications/admin/static/codemirror/lib/codemirror.js
index ac0f3241..6cfc6ff9 100644
--- a/applications/admin/static/codemirror/lib/codemirror.js
+++ b/applications/admin/static/codemirror/lib/codemirror.js
@@ -1,4 +1,4 @@
-// CodeMirror version 3.14
+// CodeMirror version 3.18
//
// CodeMirror is the only global var we claim
window.CodeMirror = (function() {
@@ -26,10 +26,11 @@ window.CodeMirror = (function() {
// This is woefully incomplete. Suggestions for alternative methods welcome.
var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
var mac = ios || /Mac/.test(navigator.platform);
- var windows = /windows/i.test(navigator.platform);
+ var windows = /win/i.test(navigator.platform);
var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
if (opera_version) opera_version = Number(opera_version[1]);
+ if (opera_version && opera_version >= 15) { opera = false; webkit = true; }
// Some browsers use the wrong event properties to signal cmd/ctrl on OS X
var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11));
var captureMiddleClick = gecko || (ie && !ie_lt9);
@@ -305,15 +306,13 @@ window.CodeMirror = (function() {
// Make sure the gutters options contains the element
// "CodeMirror-linenumbers" when the lineNumbers option is true.
function setGuttersForLineNumbers(options) {
- var found = false;
- for (var i = 0; i < options.gutters.length; ++i) {
- if (options.gutters[i] == "CodeMirror-linenumbers") {
- if (options.lineNumbers) found = true;
- else options.gutters.splice(i--, 1);
- }
+ var found = indexOf(options.gutters, "CodeMirror-linenumbers");
+ if (found == -1 && options.lineNumbers) {
+ options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
+ } else if (found > -1 && !options.lineNumbers) {
+ options.gutters = options.gutters.slice(0);
+ options.gutters.splice(found, 1);
}
- if (!found && options.lineNumbers)
- options.gutters.push("CodeMirror-linenumbers");
}
// SCROLLBARS
@@ -333,13 +332,19 @@ window.CodeMirror = (function() {
d.scrollbarV.style.bottom = needsH ? scrollbarWidth(d.measure) + "px" : "0";
d.scrollbarV.firstChild.style.height =
(scrollHeight - d.scroller.clientHeight + d.scrollbarV.clientHeight) + "px";
- } else d.scrollbarV.style.display = "";
+ } else {
+ d.scrollbarV.style.display = "";
+ d.scrollbarV.firstChild.style.height = "0";
+ }
if (needsH) {
d.scrollbarH.style.display = "block";
d.scrollbarH.style.right = needsV ? scrollbarWidth(d.measure) + "px" : "0";
d.scrollbarH.firstChild.style.width =
(d.scroller.scrollWidth - d.scroller.clientWidth + d.scrollbarH.clientWidth) + "px";
- } else d.scrollbarH.style.display = "";
+ } else {
+ d.scrollbarH.style.display = "";
+ d.scrollbarH.firstChild.style.width = "0";
+ }
if (needsH && needsV) {
d.scrollbarFiller.style.display = "block";
d.scrollbarFiller.style.height = d.scrollbarFiller.style.width = scrollbarWidth(d.measure) + "px";
@@ -403,14 +408,21 @@ window.CodeMirror = (function() {
// DISPLAY DRAWING
- function updateDisplay(cm, changes, viewPort) {
+ function updateDisplay(cm, changes, viewPort, forced) {
var oldFrom = cm.display.showingFrom, oldTo = cm.display.showingTo, updated;
var visible = visibleLines(cm.display, cm.doc, viewPort);
- for (;;) {
- if (!updateDisplayInner(cm, changes, visible)) break;
+ for (var first = true;; first = false) {
+ var oldWidth = cm.display.scroller.clientWidth;
+ if (!updateDisplayInner(cm, changes, visible, forced)) break;
updated = true;
+ changes = [];
updateSelection(cm);
updateScrollbars(cm);
+ if (first && cm.options.lineWrapping && oldWidth != cm.display.scroller.clientWidth) {
+ forced = true;
+ continue;
+ }
+ forced = false;
// Clip forced viewport to actual scrollable area
if (viewPort)
@@ -419,7 +431,6 @@ window.CodeMirror = (function() {
visible = visibleLines(cm.display, cm.doc, viewPort);
if (visible.from >= cm.display.showingFrom && visible.to <= cm.display.showingTo)
break;
- changes = [];
}
if (updated) {
@@ -433,7 +444,7 @@ window.CodeMirror = (function() {
// Uses a set of changes plus the current scroll position to
// determine which DOM updates have to be made, and makes the
// updates.
- function updateDisplayInner(cm, changes, visible) {
+ function updateDisplayInner(cm, changes, visible, forced) {
var display = cm.display, doc = cm.doc;
if (!display.wrapper.clientWidth) {
display.showingFrom = display.showingTo = doc.first;
@@ -442,7 +453,7 @@ window.CodeMirror = (function() {
}
// Bail out if the visible area is already rendered and nothing changed.
- if (changes.length == 0 &&
+ if (!forced && changes.length == 0 &&
visible.from > display.showingFrom && visible.to < display.showingTo)
return;
@@ -455,7 +466,7 @@ window.CodeMirror = (function() {
var positionsChangedFrom = Infinity;
if (cm.options.lineNumbers)
for (var i = 0; i < changes.length; ++i)
- if (changes[i].diff) { positionsChangedFrom = changes[i].from; break; }
+ if (changes[i].diff && changes[i].from < positionsChangedFrom) { positionsChangedFrom = changes[i].from; }
var end = doc.first + doc.size;
var from = Math.max(visible.from - cm.options.viewportMargin, doc.first);
@@ -495,7 +506,7 @@ window.CodeMirror = (function() {
if (range.from >= range.to) intact.splice(i--, 1);
else intactLines += range.to - range.from;
}
- if (intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
+ if (!forced && intactLines == to - from && from == display.showingFrom && to == display.showingTo) {
updateViewOffset(cm);
return;
}
@@ -520,6 +531,14 @@ window.CodeMirror = (function() {
}
display.showingFrom = from; display.showingTo = to;
+ updateHeightsInViewport(cm);
+ updateViewOffset(cm);
+
+ return true;
+ }
+
+ function updateHeightsInViewport(cm) {
+ var display = cm.display;
var prevBottom = display.lineDiv.offsetTop;
for (var node = display.lineDiv.firstChild, height; node; node = node.nextSibling) if (node.lineObj) {
if (ie_lt8) {
@@ -539,9 +558,6 @@ window.CodeMirror = (function() {
widgets[i].height = widgets[i].node.offsetHeight;
}
}
- updateViewOffset(cm);
-
- return true;
}
function updateViewOffset(cm) {
@@ -607,7 +623,7 @@ window.CodeMirror = (function() {
if (nextIntact && nextIntact.to == lineN) nextIntact = intact.shift();
if (lineIsHidden(cm.doc, line)) {
if (line.height != 0) updateLineHeight(line, 0);
- if (line.widgets && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
+ if (line.widgets && cur && cur.previousSibling) for (var i = 0; i < line.widgets.length; ++i) {
var w = line.widgets[i];
if (w.showIfHidden) {
var prev = cur.previousSibling;
@@ -652,10 +668,11 @@ window.CodeMirror = (function() {
}
function buildLineElement(cm, line, lineNo, dims, reuse) {
- var lineElement = lineContent(cm, line);
+ var built = buildLineContent(cm, line), lineElement = built.pre;
var markers = line.gutterMarkers, display = cm.display, wrap;
- if (!cm.options.lineNumbers && !markers && !line.bgClass && !line.wrapClass && !line.widgets)
+ var bgClass = built.bgClass ? built.bgClass + " " + (line.bgClass || "") : line.bgClass;
+ if (!cm.options.lineNumbers && !markers && !bgClass && !line.wrapClass && !line.widgets)
return lineElement;
// Lines with gutter elements, widgets or a background class need
@@ -670,10 +687,10 @@ window.CodeMirror = (function() {
if (!/\bCodeMirror-linewidget\b/.test(n.className)) {
reuse.removeChild(n);
} else {
- for (var i = 0, first = true; i < line.widgets.length; ++i) {
+ for (var i = 0; i < line.widgets.length; ++i) {
var widget = line.widgets[i];
- if (!widget.above) { insertBefore = n; first = false; }
if (widget.node == n.firstChild) {
+ if (!widget.above && !insertBefore) insertBefore = n;
positionLineWidget(widget, n, reuse, dims);
++widgetsSeen;
break;
@@ -693,8 +710,8 @@ window.CodeMirror = (function() {
wrap.appendChild(lineElement);
}
// Kludge to make sure the styled element lies behind the selection (by z-index)
- if (line.bgClass)
- wrap.insertBefore(elt("div", null, line.bgClass + " CodeMirror-linebackground"), wrap.firstChild);
+ if (bgClass)
+ wrap.insertBefore(elt("div", null, bgClass + " CodeMirror-linebackground"), wrap.firstChild);
if (cm.options.lineNumbers || markers) {
var gutterWrap = wrap.insertBefore(elt("div", null, null, "position: absolute; left: " +
(cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"),
@@ -866,9 +883,10 @@ window.CodeMirror = (function() {
clearInterval(display.blinker);
var on = true;
display.cursor.style.visibility = display.otherCursor.style.visibility = "";
- display.blinker = setInterval(function() {
- display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
- }, cm.options.cursorBlinkRate);
+ if (cm.options.cursorBlinkRate > 0)
+ display.blinker = setInterval(function() {
+ display.cursor.style.visibility = display.otherCursor.style.visibility = (on = !on) ? "" : "hidden";
+ }, cm.options.cursorBlinkRate);
}
// HIGHLIGHT WORKER
@@ -919,8 +937,8 @@ window.CodeMirror = (function() {
// smallest indentation, which tends to need the least context to
// parse correctly.
function findStartLine(cm, n, precise) {
- var minindent, minline, doc = cm.doc;
- for (var search = n, lim = n - 100; search > lim; --search) {
+ var minindent, minline, doc = cm.doc, maxScan = cm.doc.mode.innerMode ? 1000 : 100;
+ for (var search = n, lim = n - maxScan; search > lim; --search) {
if (search <= doc.first) return doc.first;
var line = getLine(doc, search - 1);
if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
@@ -935,7 +953,7 @@ window.CodeMirror = (function() {
function getStateBefore(cm, n, precise) {
var doc = cm.doc, display = cm.display;
- if (!doc.mode.startState) return true;
+ if (!doc.mode.startState) return true;
var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
if (!state) state = startState(doc.mode);
else state = copyState(doc.mode, state);
@@ -960,17 +978,23 @@ window.CodeMirror = (function() {
function measureChar(cm, line, ch, data, bias) {
var dir = -1;
data = data || measureLine(cm, line);
+ if (data.crude) {
+ var left = data.left + ch * data.width;
+ return {left: left, right: left + data.width, top: data.top, bottom: data.bottom};
+ }
for (var pos = ch;; pos += dir) {
var r = data[pos];
if (r) break;
if (dir < 0 && pos == 0) dir = 1;
}
- var rightV = (pos < ch || bias == "right") && r.topRight != null;
+ bias = pos > ch ? "left" : pos < ch ? "right" : bias;
+ if (bias == "left" && r.leftSide) r = r.leftSide;
+ else if (bias == "right" && r.rightSide) r = r.rightSide;
return {left: pos < ch ? r.right : r.left,
right: pos > ch ? r.left : r.right,
- top: rightV ? r.topRight : r.top,
- bottom: rightV ? r.bottomRight : r.bottom};
+ top: r.top,
+ bottom: r.bottom};
}
function findCachedMeasurement(cm, line) {
@@ -979,7 +1003,7 @@ window.CodeMirror = (function() {
var memo = cache[i];
if (memo.text == line.text && memo.markedSpans == line.markedSpans &&
cm.display.scroller.clientWidth == memo.width &&
- memo.classes == line.textClass + "|" + line.bgClass + "|" + line.wrapClass)
+ memo.classes == line.textClass + "|" + line.wrapClass)
return memo;
}
}
@@ -999,15 +1023,18 @@ window.CodeMirror = (function() {
var cache = cm.display.measureLineCache;
var memo = {text: line.text, width: cm.display.scroller.clientWidth,
markedSpans: line.markedSpans, measure: measure,
- classes: line.textClass + "|" + line.bgClass + "|" + line.wrapClass};
+ classes: line.textClass + "|" + line.wrapClass};
if (cache.length == 16) cache[++cm.display.measureLineCachePos % 16] = memo;
else cache.push(memo);
return measure;
}
function measureLineInner(cm, line) {
+ if (!cm.options.lineWrapping && line.text.length >= cm.options.crudeMeasuringFrom)
+ return crudelyMeasureLine(cm, line);
+
var display = cm.display, measure = emptyArray(line.text.length);
- var pre = lineContent(cm, line, measure);
+ var pre = buildLineContent(cm, line, measure, true).pre;
// IE does not cache element positions of inline elements between
// calls to getBoundingClientRect. This makes the loop below,
@@ -1043,52 +1070,64 @@ window.CodeMirror = (function() {
if (ie_lt9 && display.measure.first != pre)
removeChildrenAndAdd(display.measure, pre);
- function categorizeVSpan(top, bot) {
+ function measureRect(rect) {
+ var top = rect.top - outer.top, bot = rect.bottom - outer.top;
if (bot > maxBot) bot = maxBot;
if (top < 0) top = 0;
- for (var j = 0; j < vranges.length; j += 2) {
- var rtop = vranges[j], rbot = vranges[j+1];
+ for (var i = vranges.length - 2; i >= 0; i -= 2) {
+ var rtop = vranges[i], rbot = vranges[i+1];
if (rtop > bot || rbot < top) continue;
if (rtop <= top && rbot >= bot ||
top <= rtop && bot >= rbot ||
Math.min(bot, rbot) - Math.max(top, rtop) >= (bot - top) >> 1) {
- vranges[j] = Math.min(top, rtop);
- vranges[j+1] = Math.max(bot, rbot);
- return j;
+ vranges[i] = Math.min(top, rtop);
+ vranges[i+1] = Math.max(bot, rbot);
+ break;
}
}
- vranges.push(top, bot);
- return j;
+ if (i < 0) { i = vranges.length; vranges.push(top, bot); }
+ return {left: rect.left - outer.left,
+ right: rect.right - outer.left,
+ top: i, bottom: null};
+ }
+ function finishRect(rect) {
+ rect.bottom = vranges[rect.top+1];
+ rect.top = vranges[rect.top];
}
for (var i = 0, cur; i < measure.length; ++i) if (cur = measure[i]) {
- var size, node = cur;
+ var node = cur, rect = null;
// A widget might wrap, needs special care
if (/\bCodeMirror-widget\b/.test(cur.className) && cur.getClientRects) {
if (cur.firstChild.nodeType == 1) node = cur.firstChild;
- var rects = node.getClientRects(), rLeft = rects[0], rRight = rects[rects.length - 1];
+ var rects = node.getClientRects();
if (rects.length > 1) {
- var vCatLeft = categorizeVSpan(rLeft.top - outer.top, rLeft.bottom - outer.top);
- var vCatRight = categorizeVSpan(rRight.top - outer.top, rRight.bottom - outer.top);
- data[i] = {left: rLeft.left - outer.left, right: rRight.right - outer.left,
- top: vCatLeft, topRight: vCatRight};
- continue;
+ rect = data[i] = measureRect(rects[0]);
+ rect.rightSide = measureRect(rects[rects.length - 1]);
}
}
- size = getRect(node);
- var vCat = categorizeVSpan(size.top - outer.top, size.bottom - outer.top);
- var right = size.right;
- if (cur.measureRight) right = getRect(cur.measureRight).left;
- data[i] = {left: size.left - outer.left, right: right - outer.left, top: vCat};
+ if (!rect) rect = data[i] = measureRect(getRect(node));
+ if (cur.measureRight) rect.right = getRect(cur.measureRight).left;
+ if (cur.leftSide) rect.leftSide = measureRect(getRect(cur.leftSide));
}
+ removeChildren(cm.display.measure);
for (var i = 0, cur; i < data.length; ++i) if (cur = data[i]) {
- var vr = cur.top, vrRight = cur.topRight;
- cur.top = vranges[vr]; cur.bottom = vranges[vr+1];
- if (vrRight != null) { cur.topRight = vranges[vrRight]; cur.bottomRight = vranges[vrRight+1]; }
+ finishRect(cur);
+ if (cur.leftSide) finishRect(cur.leftSide);
+ if (cur.rightSide) finishRect(cur.rightSide);
}
return data;
}
+ function crudelyMeasureLine(cm, line) {
+ var copy = new Line(line.text.slice(0, 100), null);
+ if (line.textClass) copy.textClass = line.textClass;
+ var measure = measureLineInner(cm, copy);
+ var left = measureChar(cm, copy, 0, measure, "left");
+ var right = measureChar(cm, copy, 99, measure, "right");
+ return {crude: true, top: left.top, left: left.left, bottom: left.bottom, width: (right.right - left.left) / 100};
+ }
+
function measureLineWidth(cm, line) {
var hasBadSpan = false;
if (line.markedSpans) for (var i = 0; i < line.markedSpans; ++i) {
@@ -1096,9 +1135,10 @@ window.CodeMirror = (function() {
if (sp.collapsed && (sp.to == null || sp.to == line.text.length)) hasBadSpan = true;
}
var cached = !hasBadSpan && findCachedMeasurement(cm, line);
- if (cached) return measureChar(cm, line, line.text.length, cached.measure, "right").right;
+ if (cached || line.text.length >= cm.options.crudeMeasuringFrom)
+ return measureChar(cm, line, line.text.length, cached && cached.measure, "right").right;
- var pre = lineContent(cm, line);
+ var pre = buildLineContent(cm, line, null, true).pre;
var end = pre.appendChild(zeroWidthElement(cm.display.measure));
removeChildrenAndAdd(cm.display.measure, pre);
return getRect(end).right - getRect(cm.display.lineDiv).left;
@@ -1302,6 +1342,7 @@ window.CodeMirror = (function() {
// An array of ranges of lines that have to be updated. See
// updateDisplay.
changes: [],
+ forceUpdate: false,
updateInput: null,
userSelChange: null,
textChanged: null,
@@ -1334,8 +1375,8 @@ window.CodeMirror = (function() {
var coords = cursorCoords(cm, doc.sel.head);
newScrollPos = calculateScrollPos(cm, coords.left, coords.top, coords.left, coords.bottom);
}
- if (op.changes.length || newScrollPos && newScrollPos.scrollTop != null) {
- updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop);
+ if (op.changes.length || op.forceUpdate || newScrollPos && newScrollPos.scrollTop != null) {
+ updated = updateDisplay(cm, op.changes, newScrollPos && newScrollPos.scrollTop, op.forceUpdate);
if (cm.display.scroller.offsetHeight) cm.doc.scrollTop = cm.display.scroller.scrollTop;
}
if (!updated && op.selectionChanged) updateSelection(cm);
@@ -1432,6 +1473,10 @@ window.CodeMirror = (function() {
function readInput(cm) {
var input = cm.display.input, prevInput = cm.display.prevInput, doc = cm.doc, sel = doc.sel;
if (!cm.state.focused || hasSelection(input) || isReadOnly(cm) || cm.state.disableInput) return false;
+ if (cm.state.pasteIncoming && cm.state.fakedLastChar) {
+ input.value = input.value.substring(0, input.value.length - 1);
+ cm.state.fakedLastChar = false;
+ }
var text = input.value;
if (text == prevInput && posEq(sel.from, sel.to)) return false;
if (ie && !ie_lt9 && cm.display.inputHasSelection === text) {
@@ -1562,7 +1607,10 @@ window.CodeMirror = (function() {
if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
if (e.keyCode == 16) cm.doc.sel.shift = false;
}));
- on(d.input, "input", bind(fastPoll, cm));
+ on(d.input, "input", function() {
+ if (ie && !ie_lt9 && cm.display.inputHasSelection) cm.display.inputHasSelection = null;
+ fastPoll(cm);
+ });
on(d.input, "keydown", operation(cm, onKeyDown));
on(d.input, "keypress", operation(cm, onKeyPress));
on(d.input, "focus", bind(onFocus, cm));
@@ -1578,12 +1626,22 @@ window.CodeMirror = (function() {
on(d.scroller, "dragover", drag_);
on(d.scroller, "drop", operation(cm, onDrop));
}
- on(d.scroller, "paste", function(e){
+ on(d.scroller, "paste", function(e) {
if (eventInWidget(d, e)) return;
focusInput(cm);
fastPoll(cm);
});
on(d.input, "paste", function() {
+ // Workaround for webkit bug https://bugs.webkit.org/show_bug.cgi?id=90206
+ // Add a char to the end of textarea before paste occur so that
+ // selection doesn't span to the end of textarea.
+ if (webkit && !cm.state.fakedLastChar && !(new Date - cm.state.lastMiddleDown < 200)) {
+ var start = d.input.selectionStart, end = d.input.selectionEnd;
+ d.input.value += "$";
+ d.input.selectionStart = start;
+ d.input.selectionEnd = end;
+ cm.state.fakedLastChar = true;
+ }
cm.state.pasteIncoming = true;
fastPoll(cm);
});
@@ -1647,6 +1705,7 @@ window.CodeMirror = (function() {
if (captureMiddleClick) onContextMenu.call(cm, cm, e);
return;
case 2:
+ if (webkit) cm.state.lastMiddleDown = +new Date;
if (start) extendSelection(cm.doc, start);
setTimeout(bind(focusInput, cm), 20);
e_preventDefault(e);
@@ -1767,17 +1826,16 @@ window.CodeMirror = (function() {
on(document, "mouseup", up);
}
- function clickInGutter(cm, e) {
- var display = cm.display;
+ function gutterEvent(cm, e, type, prevent, signalfn) {
try { var mX = e.clientX, mY = e.clientY; }
catch(e) { return false; }
+ if (mX >= Math.floor(getRect(cm.display.gutters).right)) return false;
+ if (prevent) e_preventDefault(e);
- if (mX >= Math.floor(getRect(display.gutters).right)) return false;
- e_preventDefault(e);
- if (!hasHandler(cm, "gutterClick")) return true;
-
+ var display = cm.display;
var lineBox = getRect(display.lineDiv);
- if (mY > lineBox.bottom) return true;
+
+ if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
mY -= lineBox.top - display.viewOffset;
for (var i = 0; i < cm.options.gutters.length; ++i) {
@@ -1785,11 +1843,19 @@ window.CodeMirror = (function() {
if (g && getRect(g).right >= mX) {
var line = lineAtHeight(cm.doc, mY);
var gutter = cm.options.gutters[i];
- signalLater(cm, "gutterClick", cm, line, gutter, e);
- break;
+ signalfn(cm, type, cm, line, gutter, e);
+ return e_defaultPrevented(e);
}
}
- return true;
+ }
+
+ function contextMenuInGutter(cm, e) {
+ if (!hasHandler(cm, "gutterContextMenu")) return false;
+ return gutterEvent(cm, e, "gutterContextMenu", false, signal);
+ }
+
+ function clickInGutter(cm, e) {
+ return gutterEvent(cm, e, "gutterClick", true, signalLater);
}
// Kludge to work around strange IE behavior where it'll sometimes
@@ -1852,6 +1918,7 @@ window.CodeMirror = (function() {
// Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
if (e.dataTransfer.setDragImage && !safari) {
var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
+ img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
if (opera) {
img.width = img.height = 1;
cm.display.wrapper.appendChild(img);
@@ -2050,8 +2117,8 @@ window.CodeMirror = (function() {
function onKeyDown(e) {
var cm = this;
if (!cm.state.focused) onFocus(cm);
- if (ie && e.keyCode == 27) { e.returnValue = false; }
if (signalDOMEvent(cm, e) || cm.options.onKeyEvent && cm.options.onKeyEvent(cm, addStop(e))) return;
+ if (ie && e.keyCode == 27) e.returnValue = false;
var code = e.keyCode;
// IE does strange things with escape.
cm.doc.sel.shift = code == 16 || e.shiftKey;
@@ -2088,7 +2155,10 @@ window.CodeMirror = (function() {
cm.state.focused = true;
if (cm.display.wrapper.className.search(/\bCodeMirror-focused\b/) == -1)
cm.display.wrapper.className += " CodeMirror-focused";
- resetInput(cm, true);
+ if (!cm.curOp) {
+ resetInput(cm, true);
+ if (webkit) setTimeout(bind(resetInput, cm, true), 0); // Issue #1730
+ }
}
slowPoll(cm);
restartBlink(cm);
@@ -2105,8 +2175,9 @@ window.CodeMirror = (function() {
var detectingSelectAll;
function onContextMenu(cm, e) {
+ if (signalDOMEvent(cm, e, "contextmenu")) return;
var display = cm.display, sel = cm.doc.sel;
- if (eventInWidget(display, e)) return;
+ if (eventInWidget(display, e) || contextMenuInGutter(cm, e)) return;
var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
if (!pos || opera) return; // Opera is difficult.
@@ -2125,8 +2196,8 @@ window.CodeMirror = (function() {
function prepareSelectAllHack() {
if (display.input.selectionStart != null) {
- var extval = display.input.value = " " + (posEq(sel.from, sel.to) ? "" : display.input.value);
- display.prevInput = " ";
+ var extval = display.input.value = "\u200b" + (posEq(sel.from, sel.to) ? "" : display.input.value);
+ display.prevInput = "\u200b";
display.input.selectionStart = 1; display.input.selectionEnd = extval.length;
}
}
@@ -2260,6 +2331,7 @@ window.CodeMirror = (function() {
}
function makeChangeNoReadonly(doc, change, selUpdate) {
+ if (change.text.length == 1 && change.text[0] == "" && posEq(change.from, change.to)) return;
var selAfter = computeSelAfterChange(doc, change, selUpdate);
addToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
@@ -2482,6 +2554,7 @@ window.CodeMirror = (function() {
var sel = doc.sel;
sel.goalColumn = null;
+ if (bias == null) bias = posLess(head, sel.head) ? -1 : 1;
// Skip over atomic spans.
if (checkAtomic || !posEq(anchor, sel.anchor))
anchor = skipAtomic(doc, anchor, bias, checkAtomic != "push");
@@ -2755,7 +2828,7 @@ window.CodeMirror = (function() {
function findWordAt(line, pos) {
var start = pos.ch, end = pos.ch;
if (line) {
- if (pos.xRel < 0 || end == line.length) --start; else ++end;
+ if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
var startChar = line.charAt(start);
var check = isWordChar(startChar) ? isWordChar
: /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
@@ -2796,7 +2869,7 @@ window.CodeMirror = (function() {
removeKeyMap: function(map) {
var maps = this.state.keyMaps;
for (var i = 0; i < maps.length; ++i)
- if ((typeof map == "string" ? maps[i].name : maps[i]) == map) {
+ if (maps[i] == map || (typeof maps[i] != "string" && maps[i].name == map)) {
maps.splice(i, 1);
return true;
}
@@ -2860,6 +2933,7 @@ window.CodeMirror = (function() {
pos = clipPos(this.doc, pos);
var styles = getLineStyles(this, getLine(this.doc, pos.line));
var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
+ if (ch == 0) return styles[2];
for (;;) {
var mid = (before + after) >> 1;
if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
@@ -2868,6 +2942,20 @@ window.CodeMirror = (function() {
}
},
+ getModeAt: function(pos) {
+ var mode = this.doc.mode;
+ if (!mode.innerMode) return mode;
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
+ },
+
+ getHelper: function(pos, type) {
+ if (!helpers.hasOwnProperty(type)) return;
+ var help = helpers[type], mode = this.getModeAt(pos);
+ return mode[type] && help[mode[type]] ||
+ mode.helperType && help[mode.helperType] ||
+ help[mode.name];
+ },
+
getStateAfter: function(line, precise) {
var doc = this.doc;
line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
@@ -3097,24 +3185,25 @@ window.CodeMirror = (function() {
updateScrollPos(this, sPos.scrollLeft, sPos.scrollTop);
}),
- setSize: function(width, height) {
+ setSize: operation(null, function(width, height) {
function interpret(val) {
return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
}
if (width != null) this.display.wrapper.style.width = interpret(width);
if (height != null) this.display.wrapper.style.height = interpret(height);
- this.refresh();
- },
-
- on: function(type, f) {on(this, type, f);},
- off: function(type, f) {off(this, type, f);},
+ if (this.options.lineWrapping)
+ this.display.measureLineCache.length = this.display.measureLineCachePos = 0;
+ this.curOp.forceUpdate = true;
+ }),
operation: function(f){return runInOp(this, f);},
refresh: operation(null, function() {
+ var badHeight = this.display.cachedTextHeight == null;
clearCaches(this);
updateScrollPos(this, this.doc.scrollLeft, this.doc.scrollTop);
regChange(this);
+ if (badHeight) estimateLineHeights(this);
}),
swapDoc: operation(null, function(doc) {
@@ -3132,6 +3221,7 @@ window.CodeMirror = (function() {
getScrollerElement: function(){return this.display.scroller;},
getGutterElement: function(){return this.display.gutters;}
};
+ eventMixin(CodeMirror);
// OPTION DEFAULTS
@@ -3214,6 +3304,7 @@ window.CodeMirror = (function() {
option("historyEventDelay", 500);
option("viewportMargin", 10, function(cm){cm.refresh();}, true);
option("maxHighlightLength", 10000, function(cm){loadMode(cm); cm.refresh();}, true);
+ option("crudeMeasuringFrom", 10000);
option("moveInputWithCursor", true, function(cm, val) {
if (!val) cm.display.inputDiv.style.top = cm.display.inputDiv.style.left = 0;
});
@@ -3256,7 +3347,7 @@ window.CodeMirror = (function() {
};
CodeMirror.getMode = function(options, spec) {
- spec = CodeMirror.resolveMode(spec);
+ var spec = CodeMirror.resolveMode(spec);
var mfactory = modes[spec.name];
if (!mfactory) return CodeMirror.getMode(options, "text/plain");
var modeObj = mfactory(options, spec);
@@ -3269,6 +3360,7 @@ window.CodeMirror = (function() {
}
}
modeObj.name = spec.name;
+
return modeObj;
};
@@ -3296,6 +3388,16 @@ window.CodeMirror = (function() {
var initHooks = [];
CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
+ var helpers = CodeMirror.helpers = {};
+ CodeMirror.registerHelper = function(type, name, value) {
+ if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {};
+ helpers[type][name] = value;
+ };
+
+ // UTILITIES
+
+ CodeMirror.isWordChar = isWordChar;
+
// MODE STATE HANDLING
// Utility functions for working with state. Exported because modes
@@ -3321,6 +3423,7 @@ window.CodeMirror = (function() {
CodeMirror.innerMode = function(mode, state) {
while (mode.innerMode) {
var info = mode.innerMode(state);
+ if (!info || info.mode == mode) break;
state = info.state;
mode = info.mode;
}
@@ -3633,11 +3736,16 @@ window.CodeMirror = (function() {
this.doc = doc;
}
CodeMirror.TextMarker = TextMarker;
+ eventMixin(TextMarker);
TextMarker.prototype.clear = function() {
if (this.explicitlyCleared) return;
var cm = this.doc.cm, withOp = cm && !cm.curOp;
if (withOp) startOperation(cm);
+ if (hasHandler(this, "clear")) {
+ var found = this.find();
+ if (found) signalLater(this, "clear", found.from, found.to);
+ }
var min = null, max = null;
for (var i = 0; i < this.lines.length; ++i) {
var line = this.lines[i];
@@ -3666,7 +3774,6 @@ window.CodeMirror = (function() {
if (cm) reCheckSelection(cm);
}
if (withOp) endOperation(cm);
- signalLater(this, "clear");
};
TextMarker.prototype.find = function() {
@@ -3687,14 +3794,17 @@ window.CodeMirror = (function() {
TextMarker.prototype.changed = function() {
var pos = this.find(), cm = this.doc.cm;
if (!pos || !cm) return;
- var line = getLine(this.doc, pos.from.line);
+ if (this.type != "bookmark") pos = pos.from;
+ var line = getLine(this.doc, pos.line);
clearCachedMeasurement(cm, line);
- if (pos.from.line >= cm.display.showingFrom && pos.from.line < cm.display.showingTo) {
+ if (pos.line >= cm.display.showingFrom && pos.line < cm.display.showingTo) {
for (var node = cm.display.lineDiv.firstChild; node; node = node.nextSibling) if (node.lineObj == line) {
if (node.offsetHeight != line.height) updateLineHeight(line, node.offsetHeight);
break;
}
- runInOp(cm, function() { cm.curOp.selectionChanged = true; });
+ runInOp(cm, function() {
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = cm.curOp.updateMaxLine = true;
+ });
}
};
@@ -3767,7 +3877,7 @@ window.CodeMirror = (function() {
}
if (cm) {
if (updateMaxLine) cm.curOp.updateMaxLine = true;
- if (marker.className || marker.startStyle || marker.endStyle || marker.collapsed)
+ if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.collapsed)
regChange(cm, from.line, to.line + 1);
if (marker.atomic) reCheckSelection(cm);
}
@@ -3785,6 +3895,7 @@ window.CodeMirror = (function() {
}
}
CodeMirror.SharedTextMarker = SharedTextMarker;
+ eventMixin(SharedTextMarker);
SharedTextMarker.prototype.clear = function() {
if (this.explicitlyCleared) return;
@@ -4037,11 +4148,12 @@ window.CodeMirror = (function() {
// LINE WIDGETS
var LineWidget = CodeMirror.LineWidget = function(cm, node, options) {
- for (var opt in options) if (options.hasOwnProperty(opt))
+ if (options) for (var opt in options) if (options.hasOwnProperty(opt))
this[opt] = options[opt];
this.cm = cm;
this.node = node;
};
+ eventMixin(LineWidget);
function widgetOperation(f) {
return function() {
var withOp = !this.cm.curOp;
@@ -4056,7 +4168,9 @@ window.CodeMirror = (function() {
if (no == null || !ws) return;
for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
if (!ws.length) this.line.widgets = null;
+ var aboveVisible = heightAtLine(this.cm, this.line) < this.cm.doc.scrollTop;
updateLineHeight(this.line, Math.max(0, this.line.height - widgetHeight(this)));
+ if (aboveVisible) addToScrollPos(this.cm, 0, -this.height);
regChange(this.cm, no, no + 1);
});
LineWidget.prototype.changed = widgetOperation(function() {
@@ -4080,10 +4194,12 @@ window.CodeMirror = (function() {
var widget = new LineWidget(cm, node, options);
if (widget.noHScroll) cm.display.alignWidgets = true;
changeLine(cm, handle, function(line) {
- (line.widgets || (line.widgets = [])).push(widget);
+ var widgets = line.widgets || (line.widgets = []);
+ if (widget.insertAt == null) widgets.push(widget);
+ else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
widget.line = line;
if (!lineIsHidden(cm.doc, line) || widget.showIfHidden) {
- var aboveVisible = heightAtLine(cm, line) < cm.display.scroller.scrollTop;
+ var aboveVisible = heightAtLine(cm, line) < cm.doc.scrollTop;
updateLineHeight(line, line.height + widgetHeight(widget));
if (aboveVisible) addToScrollPos(cm, 0, widget.height);
}
@@ -4096,12 +4212,12 @@ window.CodeMirror = (function() {
// Line objects. These hold state related to a line, including
// highlighting info (the styles array).
- function makeLine(text, markedSpans, estimateHeight) {
- var line = {text: text};
- attachMarkedSpans(line, markedSpans);
- line.height = estimateHeight ? estimateHeight(line) : 1;
- return line;
- }
+ var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
+ this.text = text;
+ attachMarkedSpans(this, markedSpans);
+ this.height = estimateHeight ? estimateHeight(this) : 1;
+ };
+ eventMixin(Line);
function updateLine(line, text, markedSpans, estimateHeight) {
line.text = text;
@@ -4131,8 +4247,7 @@ window.CodeMirror = (function() {
while (!stream.eol()) {
if (stream.pos > cm.options.maxHighlightLength) {
flattenSpans = false;
- // Webkit seems to refuse to render text nodes longer than 57444 characters
- stream.pos = Math.min(text.length, stream.start + 50000);
+ stream.pos = text.length;
style = null;
} else {
style = mode.token(stream, state);
@@ -4143,7 +4258,12 @@ window.CodeMirror = (function() {
}
stream.start = stream.pos;
}
- if (curStart < stream.pos) f(stream.pos, curStyle);
+ while (curStart < stream.pos) {
+ // Webkit seems to refuse to render text nodes longer than 57444 characters
+ var pos = Math.min(stream.pos, curStart + 50000);
+ f(pos, curStyle);
+ curStart = pos;
+ }
}
function highlightLine(cm, line, state) {
@@ -4201,20 +4321,30 @@ window.CodeMirror = (function() {
}
var styleToClassCache = {};
- function styleToClass(style) {
+ function interpretTokenStyle(style, builder) {
if (!style) return null;
+ for (;;) {
+ var lineClass = style.match(/(?:^|\s)line-(background-)?(\S+)/);
+ if (!lineClass) break;
+ style = style.slice(0, lineClass.index) + style.slice(lineClass.index + lineClass[0].length);
+ var prop = lineClass[1] ? "bgClass" : "textClass";
+ if (builder[prop] == null)
+ builder[prop] = lineClass[2];
+ else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(builder[prop]))
+ builder[prop] += " " + lineClass[2];
+ }
return styleToClassCache[style] ||
(styleToClassCache[style] = "cm-" + style.replace(/ +/g, " cm-"));
}
- function lineContent(cm, realLine, measure) {
+ function buildLineContent(cm, realLine, measure, copyWidgets) {
var merged, line = realLine, empty = true;
while (merged = collapsedSpanAtStart(line))
line = getLine(cm.doc, merged.find().from.line);
- var builder = {pre: elt("pre"), col: 0, pos: 0, display: !measure,
- measure: null, measuredSomething: false, cm: cm};
- if (line.textClass) builder.pre.className = line.textClass;
+ var builder = {pre: elt("pre"), col: 0, pos: 0,
+ measure: null, measuredSomething: false, cm: cm,
+ copyWidgets: copyWidgets};
do {
if (line.text) empty = false;
@@ -4251,12 +4381,15 @@ window.CodeMirror = (function() {
}
}
+ var textClass = builder.textClass ? builder.textClass + " " + (realLine.textClass || "") : realLine.textClass;
+ if (textClass) builder.pre.className = textClass;
+
signal(cm, "renderLine", cm, realLine, builder.pre);
- return builder.pre;
+ return builder;
}
var tokenSpecialChars = /[\t\u0000-\u0019\u00ad\u200b\u2028\u2029\uFEFF]/g;
- function buildToken(builder, text, style, startStyle, endStyle) {
+ function buildToken(builder, text, style, startStyle, endStyle, title) {
if (!text) return;
if (!tokenSpecialChars.test(text)) {
builder.col += text.length;
@@ -4289,7 +4422,9 @@ window.CodeMirror = (function() {
var fullStyle = style || "";
if (startStyle) fullStyle += startStyle;
if (endStyle) fullStyle += endStyle;
- return builder.pre.appendChild(elt("span", [content], fullStyle));
+ var token = elt("span", [content], fullStyle);
+ if (title) token.title = title;
+ return builder.pre.appendChild(token);
}
builder.pre.appendChild(content);
}
@@ -4304,9 +4439,11 @@ window.CodeMirror = (function() {
} else if (i && wrapping && spanAffectsWrapping(text, i)) {
builder.pre.appendChild(elt("wbr"));
}
+ var old = builder.measure[builder.pos];
var span = builder.measure[builder.pos] =
buildToken(builder, ch, style,
start && startStyle, i == text.length - 1 && endStyle);
+ if (old) span.leftSide = old.leftSide || old;
// In IE single-space nodes wrap differently than spaces
// embedded in larger text nodes, except when set to
// white-space: normal (issue #1268).
@@ -4325,20 +4462,30 @@ window.CodeMirror = (function() {
out += " ";
return out;
}
- return function(builder, text, style, startStyle, endStyle) {
- return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle);
+ return function(builder, text, style, startStyle, endStyle, title) {
+ return inner(builder, text.replace(/ {3,}/, split), style, startStyle, endStyle, title);
};
}
- function buildCollapsedSpan(builder, size, widget) {
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
+ var widget = !ignoreWidget && marker.replacedWith;
if (widget) {
- if (!builder.display) widget = widget.cloneNode(true);
+ if (builder.copyWidgets) widget = widget.cloneNode(true);
+ builder.pre.appendChild(widget);
if (builder.measure) {
- builder.measure[builder.pos] = size ? widget
- : builder.pre.appendChild(zeroWidthElement(builder.cm.display.measure));
+ if (size) {
+ builder.measure[builder.pos] = widget;
+ } else {
+ var elt = zeroWidthElement(builder.cm.display.measure);
+ if (marker.type == "bookmark" && !marker.insertLeft)
+ builder.measure[builder.pos] = builder.pre.appendChild(elt);
+ else if (builder.measure[builder.pos])
+ return;
+ else
+ builder.measure[builder.pos] = builder.pre.insertBefore(elt, widget);
+ }
builder.measuredSomething = true;
}
- builder.pre.appendChild(widget);
}
builder.pos += size;
}
@@ -4349,17 +4496,17 @@ window.CodeMirror = (function() {
var spans = line.markedSpans, allText = line.text, at = 0;
if (!spans) {
for (var i = 1; i < styles.length; i+=2)
- builder.addToken(builder, allText.slice(at, at = styles[i]), styleToClass(styles[i+1]));
+ builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder));
return;
}
var len = allText.length, pos = 0, i = 1, text = "", style;
- var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed;
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
for (;;) {
if (nextChange == pos) { // Update current marker set
- spanStyle = spanEndStyle = spanStartStyle = "";
+ spanStyle = spanEndStyle = spanStartStyle = title = "";
collapsed = null; nextChange = Infinity;
- var foundBookmark = null;
+ var foundBookmarks = [];
for (var j = 0; j < spans.length; ++j) {
var sp = spans[j], m = sp.marker;
if (sp.from <= pos && (sp.to == null || sp.to > pos)) {
@@ -4367,20 +4514,21 @@ window.CodeMirror = (function() {
if (m.className) spanStyle += " " + m.className;
if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
+ if (m.title && !title) title = m.title;
if (m.collapsed && (!collapsed || collapsed.marker.size < m.size))
collapsed = sp;
} else if (sp.from > pos && nextChange > sp.from) {
nextChange = sp.from;
}
- if (m.type == "bookmark" && sp.from == pos && m.replacedWith)
- foundBookmark = m.replacedWith;
+ if (m.type == "bookmark" && sp.from == pos && m.replacedWith) foundBookmarks.push(m);
}
if (collapsed && (collapsed.from || 0) == pos) {
buildCollapsedSpan(builder, (collapsed.to == null ? len : collapsed.to) - pos,
- collapsed.from != null && collapsed.marker.replacedWith);
+ collapsed.marker, collapsed.from == null);
if (collapsed.to == null) return collapsed.marker.find();
}
- if (foundBookmark && !collapsed) buildCollapsedSpan(builder, 0, foundBookmark);
+ if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
+ buildCollapsedSpan(builder, 0, foundBookmarks[j]);
}
if (pos >= len) break;
@@ -4391,14 +4539,14 @@ window.CodeMirror = (function() {
if (!collapsed) {
var tokenText = end > upto ? text.slice(0, upto - pos) : text;
builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
- spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "");
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title);
}
if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
pos = end;
spanStartStyle = "";
}
text = allText.slice(at, at = styles[i++]);
- style = styleToClass(styles[i++]);
+ style = interpretTokenStyle(styles[i++], builder);
}
}
}
@@ -4421,7 +4569,7 @@ window.CodeMirror = (function() {
// This is a whole-line replace. Treated specially to make
// sure line objects move the way they are supposed to.
for (var i = 0, e = text.length - 1, added = []; i < e; ++i)
- added.push(makeLine(text[i], spansFor(i), estimateHeight));
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
update(lastLine, lastLine.text, lastSpans);
if (nlines) doc.remove(from.line, nlines);
if (added.length) doc.insert(from.line, added);
@@ -4430,8 +4578,8 @@ window.CodeMirror = (function() {
update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
} else {
for (var added = [], i = 1, e = text.length - 1; i < e; ++i)
- added.push(makeLine(text[i], spansFor(i), estimateHeight));
- added.push(makeLine(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
+ added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
doc.insert(from.line + 1, added);
}
@@ -4442,7 +4590,7 @@ window.CodeMirror = (function() {
update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
for (var i = 1, e = text.length - 1, added = []; i < e; ++i)
- added.push(makeLine(text[i], spansFor(i), estimateHeight));
+ added.push(new Line(text[i], spansFor(i), estimateHeight));
if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
doc.insert(from.line + 1, added);
}
@@ -4585,7 +4733,7 @@ window.CodeMirror = (function() {
if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
if (firstLine == null) firstLine = 0;
- BranchChunk.call(this, [new LeafChunk([makeLine("", null)])]);
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
this.first = firstLine;
this.scrollTop = this.scrollLeft = 0;
this.cantEdit = false;
@@ -4650,6 +4798,11 @@ window.CodeMirror = (function() {
getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
getLineNumber: function(line) {return lineNo(line);},
+ getLineHandleVisualStart: function(line) {
+ if (typeof line == "number") line = getLine(this, line);
+ return visualLine(this, line);
+ },
+
lineCount: function() {return this.size;},
firstLine: function() {return this.first;},
lastLine: function() {return this.first + this.size - 1;},
@@ -4671,11 +4824,11 @@ window.CodeMirror = (function() {
if (extend) extendSelection(this, pos);
else setSelection(this, pos, pos);
}),
- setSelection: docOperation(function(anchor, head) {
- setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor));
+ setSelection: docOperation(function(anchor, head, bias) {
+ setSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), bias);
}),
- extendSelection: docOperation(function(from, to) {
- extendSelection(this, clipPos(this, from), to && clipPos(this, to));
+ extendSelection: docOperation(function(from, to, bias) {
+ extendSelection(this, clipPos(this, from), to && clipPos(this, to), bias);
}),
getSelection: function(lineSep) {return this.getRange(this.sel.from, this.sel.to, lineSep);},
@@ -4820,6 +4973,8 @@ window.CodeMirror = (function() {
return function() {return method.apply(this.doc, arguments);};
})(Doc.prototype[prop]);
+ eventMixin(Doc);
+
function linkedDocs(doc, f, sharedHistOnly) {
function propagate(doc, skip, sharedHist) {
if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
@@ -4963,7 +5118,8 @@ window.CodeMirror = (function() {
}
function historyChangeFromChange(doc, change) {
- var histChange = {from: change.from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
+ var from = { line: change.from.line, ch: change.from.ch };
+ var histChange = {from: from, to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
return histChange;
@@ -5183,9 +5339,9 @@ window.CodeMirror = (function() {
delayedCallbacks.push(bnd(arr[i]));
}
- function signalDOMEvent(cm, e) {
- signal(cm, e.type, cm, e);
- return e_defaultPrevented(e);
+ function signalDOMEvent(cm, e, override) {
+ signal(cm, override || e.type, cm, e);
+ return e_defaultPrevented(e) || e.codemirrorIgnore;
}
function fireDelayed() {
@@ -5202,6 +5358,11 @@ window.CodeMirror = (function() {
CodeMirror.on = on; CodeMirror.off = off; CodeMirror.signal = signal;
+ function eventMixin(ctor) {
+ ctor.prototype.on = function(type, f) {on(this, type, f);};
+ ctor.prototype.off = function(type, f) {off(this, type, f);};
+ }
+
// MISC UTILITIES
// Number of pixels added to scroller and sizer to hide scrollbar
@@ -5353,11 +5514,18 @@ window.CodeMirror = (function() {
spanAffectsWrapping = function(str, i) {
return /\-[^ \-?]|\?[^ !\'\"\),.\-\/:;\?\]\}]/.test(str.slice(i - 1, i + 1));
};
+ else if (webkit && /Chrome\/(?:29|[3-9]\d|\d\d\d)\./.test(navigator.userAgent))
+ spanAffectsWrapping = function(str, i) {
+ var code = str.charCodeAt(i - 1);
+ return code >= 8208 && code <= 8212;
+ };
else if (webkit)
spanAffectsWrapping = function(str, i) {
- if (i > 1 && str.charCodeAt(i - 1) == 45 && /\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i)))
- return true;
- return /[~!#%&*)=+}\]|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
+ if (i > 1 && str.charCodeAt(i - 1) == 45) {
+ if (/\w/.test(str.charAt(i - 2)) && /[^\-?\.]/.test(str.charAt(i))) return true;
+ if (i > 2 && /[\d\.,]/.test(str.charAt(i - 2)) && /[\d\.,]/.test(str.charAt(i))) return false;
+ }
+ return /[~!#%&*)=+}\]\\|\"\.>,:;][({[<]|-[^\-?\.\u2010-\u201f\u2026]|\?[\w~`@#$%\^&*(_=+{[|><]|…[\w~`@#$%\^&*(_=+{[><]/.test(str.slice(i - 1, i + 1));
};
var knownScrollbarWidth;
@@ -5443,11 +5611,15 @@ window.CodeMirror = (function() {
function iterateBidiSections(order, from, to, f) {
if (!order) return f(from, to, "ltr");
+ var found = false;
for (var i = 0; i < order.length; ++i) {
var part = order[i];
- if (part.from < to && part.to > from || from == to && part.to == from)
+ if (part.from < to && part.to > from || from == to && part.to == from) {
f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
+ found = true;
+ }
}
+ if (!found) f(from, to, "ltr");
}
function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
@@ -5709,7 +5881,7 @@ window.CodeMirror = (function() {
// THE END
- CodeMirror.version = "3.14.0";
+ CodeMirror.version = "3.18.0";
return CodeMirror;
})();
diff --git a/applications/admin/static/codemirror/mode/apl/index.html b/applications/admin/static/codemirror/mode/apl/index.html
index 119ff17f..f8282ac4 100644
--- a/applications/admin/static/codemirror/mode/apl/index.html
+++ b/applications/admin/static/codemirror/mode/apl/index.html
@@ -1,20 +1,32 @@
-
-
-
- CodeMirror: APL mode
-
-
-
-
-
-
-
-
- CodeMirror: APL mode
+
+

+
+
+
+
+
+APL mode
MIME types defined: text/apl (APL code)
-
-
+
diff --git a/applications/admin/static/codemirror/mode/asterisk/index.html b/applications/admin/static/codemirror/mode/asterisk/index.html
index 0a796a01..6abdecb5 100644
--- a/applications/admin/static/codemirror/mode/asterisk/index.html
+++ b/applications/admin/static/codemirror/mode/asterisk/index.html
@@ -1,20 +1,33 @@
-
-
-
- CodeMirror: Asterisk dialplan mode
-
-
-
-
-
-
-
- CodeMirror: Asterisk dialplan mode
-