(function() {
// A minilanguage for instantiating linked CodeMirror instances and Docs
function instantiateSpec(spec, place, opts) {
var names = {}, pos = 0, l = spec.length, editors = [];
while (spec) {
var m = spec.match(/^(\w+)(\*?)(?:='([^\']*)'|<(~?)(\w+)(?:\/(\d+)-(\d+))?)\s*/);
var name = m[1], isDoc = m[2], cur;
if (m[3]) {
cur = isDoc ? CodeMirror.Doc(m[3]) : CodeMirror(place, clone(opts, {value: m[3]}));
} else {
var other = m[5];
if (!names.hasOwnProperty(other)) {
names[other] = editors.length;
editors.push(CodeMirror(place, opts));
}
var doc = editors[names[other]].linkedDoc({
sharedHist: !m[4],
from: m[6] ? Number(m[6]) : null,
to: m[7] ? Number(m[7]) : null
});
cur = isDoc ? doc : CodeMirror(place, clone(opts, {value: doc}));
}
names[name] = editors.length;
editors.push(cur);
spec = spec.slice(m[0].length);
}
return editors;
}
function clone(obj, props) {
if (!obj) return;
clone.prototype = obj;
var inst = new clone();
if (props) for (var n in props) if (props.hasOwnProperty(n))
inst[n] = props[n];
return inst;
}
function eqAll(val) {
var end = arguments.length, msg = null;
if (typeof arguments[end-1] == "string")
msg = arguments[--end];
if (i == end) throw new Error("No editors provided to eqAll");
for (var i = 1; i < end; ++i)
eq(arguments[i].getValue(), val, msg)
}
function testDoc(name, spec, run, opts, expectFail) {
if (!opts) opts = {};
return test("doc_" + name, function() {
var place = document.getElementById("testground");
var editors = instantiateSpec(spec, place, opts);
var successful = false;
try {
run.apply(null, editors);
successful = true;
} finally {
if ((debug && !successful) || verbose) {
place.style.visibility = "visible";
} else {
for (var i = 0; i < editors.length; ++i)
if (editors[i] instanceof CodeMirror)
place.removeChild(editors[i].getWrapperElement());
}
}
}, expectFail);
}
var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
function testBasic(a, b) {
eqAll("x", a, b);
a.setValue("hey");
eqAll("hey", a, b);
b.setValue("wow");
eqAll("wow", a, b);
a.replaceRange("u\nv\nw", Pos(0, 3));
b.replaceRange("i", Pos(0, 4));
b.replaceRange("j", Pos(2, 1));
eqAll("wowui\nv\nwj", a, b);
}
testDoc("basic", "A='x' B 0, "not at left");
is(pos.top > 0, "not at top");
});
testDoc("copyDoc", "A='u'", function(a) {
var copy = a.getDoc().copy(true);
a.setValue("foo");
copy.setValue("bar");
var old = a.swapDoc(copy);
eq(a.getValue(), "bar");
a.undo();
eq(a.getValue(), "u");
a.swapDoc(old);
eq(a.getValue(), "foo");
eq(old.historySize().undo, 1);
eq(old.copy(false).historySize().undo, 0);
});
testDoc("docKeepsMode", "A='1+1'", function(a) {
var other = CodeMirror.Doc("hi", "text/x-markdown");
a.setOption("mode", "text/javascript");
var old = a.swapDoc(other);
eq(a.getOption("mode"), "text/x-markdown");
eq(a.getMode().name, "markdown");
a.swapDoc(old);
eq(a.getOption("mode"), "text/javascript");
eq(a.getMode().name, "javascript");
});
testDoc("subview", "A='1\n2\n3\n4\n5' B<~A/1-3", function(a, b) {
eq(b.getValue(), "2\n3");
eq(b.firstLine(), 1);
b.setCursor(Pos(4));
eqPos(b.getCursor(), Pos(2, 1));
a.replaceRange("-1\n0\n", Pos(0, 0));
eq(b.firstLine(), 3);
eqPos(b.getCursor(), Pos(4, 1));
a.undo();
eqPos(b.getCursor(), Pos(2, 1));
b.replaceRange("oyoy\n", Pos(2, 0));
eq(a.getValue(), "1\n2\noyoy\n3\n4\n5");
b.undo();
eq(a.getValue(), "1\n2\n3\n4\n5");
});
testDoc("subviewEditOnBoundary", "A='11\n22\n33\n44\n55' B<~A/1-4", function(a, b) {
a.replaceRange("x\nyy\nz", Pos(0, 1), Pos(2, 1));
eq(b.firstLine(), 2);
eq(b.lineCount(), 2);
eq(b.getValue(), "z3\n44");
a.replaceRange("q\nrr\ns", Pos(3, 1), Pos(4, 1));
eq(b.firstLine(), 2);
eq(b.getValue(), "z3\n4q");
eq(a.getValue(), "1x\nyy\nz3\n4q\nrr\ns5");
a.execCommand("selectAll");
a.replaceSelection("!");
eqAll("!", a, b);
});
testDoc("sharedMarker", "A='ab\ncd\nef\ngh' B