(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