Path: blob/master/web-gui/buildyourownbotnet/assets/js/codemirror/test/test.js
1293 views
var Pos = CodeMirror.Pos;12CodeMirror.defaults.rtlMoveVisually = true;34function forEach(arr, f) {5for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);6}78function addDoc(cm, width, height) {9var content = [], line = "";10for (var i = 0; i < width; ++i) line += "x";11for (var i = 0; i < height; ++i) content.push(line);12cm.setValue(content.join("\n"));13}1415function byClassName(elt, cls) {16if (elt.getElementsByClassName) return elt.getElementsByClassName(cls);17var found = [], re = new RegExp("\\b" + cls + "\\b");18function search(elt) {19if (elt.nodeType == 3) return;20if (re.test(elt.className)) found.push(elt);21for (var i = 0, e = elt.childNodes.length; i < e; ++i)22search(elt.childNodes[i]);23}24search(elt);25return found;26}2728var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);29var mac = /Mac/.test(navigator.platform);30var phantom = /PhantomJS/.test(navigator.userAgent);31var opera = /Opera\/\./.test(navigator.userAgent);32var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/);33if (opera_version) opera_version = Number(opera_version);34var opera_lt10 = opera && (!opera_version || opera_version < 10);3536namespace = "core_";3738test("core_fromTextArea", function() {39var te = document.getElementById("code");40te.value = "CONTENT";41var cm = CodeMirror.fromTextArea(te);42is(!te.offsetHeight);43eq(cm.getValue(), "CONTENT");44cm.setValue("foo\nbar");45eq(cm.getValue(), "foo\nbar");46cm.save();47is(/^foo\r?\nbar$/.test(te.value));48cm.setValue("xxx");49cm.toTextArea();50is(te.offsetHeight);51eq(te.value, "xxx");52});5354testCM("getRange", function(cm) {55eq(cm.getLine(0), "1234");56eq(cm.getLine(1), "5678");57eq(cm.getLine(2), null);58eq(cm.getLine(-1), null);59eq(cm.getRange(Pos(0, 0), Pos(0, 3)), "123");60eq(cm.getRange(Pos(0, -1), Pos(0, 200)), "1234");61eq(cm.getRange(Pos(0, 2), Pos(1, 2)), "34\n56");62eq(cm.getRange(Pos(1, 2), Pos(100, 0)), "78");63}, {value: "1234\n5678"});6465testCM("replaceRange", function(cm) {66eq(cm.getValue(), "");67cm.replaceRange("foo\n", Pos(0, 0));68eq(cm.getValue(), "foo\n");69cm.replaceRange("a\nb", Pos(0, 1));70eq(cm.getValue(), "fa\nboo\n");71eq(cm.lineCount(), 3);72cm.replaceRange("xyzzy", Pos(0, 0), Pos(1, 1));73eq(cm.getValue(), "xyzzyoo\n");74cm.replaceRange("abc", Pos(0, 0), Pos(10, 0));75eq(cm.getValue(), "abc");76eq(cm.lineCount(), 1);77});7879testCM("selection", function(cm) {80cm.setSelection(Pos(0, 4), Pos(2, 2));81is(cm.somethingSelected());82eq(cm.getSelection(), "11\n222222\n33");83eqPos(cm.getCursor(false), Pos(2, 2));84eqPos(cm.getCursor(true), Pos(0, 4));85cm.setSelection(Pos(1, 0));86is(!cm.somethingSelected());87eq(cm.getSelection(), "");88eqPos(cm.getCursor(true), Pos(1, 0));89cm.replaceSelection("abc");90eq(cm.getSelection(), "abc");91eq(cm.getValue(), "111111\nabc222222\n333333");92cm.replaceSelection("def", "end");93eq(cm.getSelection(), "");94eqPos(cm.getCursor(true), Pos(1, 3));95cm.setCursor(Pos(2, 1));96eqPos(cm.getCursor(true), Pos(2, 1));97cm.setCursor(1, 2);98eqPos(cm.getCursor(true), Pos(1, 2));99}, {value: "111111\n222222\n333333"});100101testCM("extendSelection", function(cm) {102cm.setExtending(true);103addDoc(cm, 10, 10);104cm.setSelection(Pos(3, 5));105eqPos(cm.getCursor("head"), Pos(3, 5));106eqPos(cm.getCursor("anchor"), Pos(3, 5));107cm.setSelection(Pos(2, 5), Pos(5, 5));108eqPos(cm.getCursor("head"), Pos(5, 5));109eqPos(cm.getCursor("anchor"), Pos(2, 5));110eqPos(cm.getCursor("start"), Pos(2, 5));111eqPos(cm.getCursor("end"), Pos(5, 5));112cm.setSelection(Pos(5, 5), Pos(2, 5));113eqPos(cm.getCursor("head"), Pos(2, 5));114eqPos(cm.getCursor("anchor"), Pos(5, 5));115eqPos(cm.getCursor("start"), Pos(2, 5));116eqPos(cm.getCursor("end"), Pos(5, 5));117cm.extendSelection(Pos(3, 2));118eqPos(cm.getCursor("head"), Pos(3, 2));119eqPos(cm.getCursor("anchor"), Pos(5, 5));120cm.extendSelection(Pos(6, 2));121eqPos(cm.getCursor("head"), Pos(6, 2));122eqPos(cm.getCursor("anchor"), Pos(5, 5));123cm.extendSelection(Pos(6, 3), Pos(6, 4));124eqPos(cm.getCursor("head"), Pos(6, 4));125eqPos(cm.getCursor("anchor"), Pos(5, 5));126cm.extendSelection(Pos(0, 3), Pos(0, 4));127eqPos(cm.getCursor("head"), Pos(0, 3));128eqPos(cm.getCursor("anchor"), Pos(5, 5));129cm.extendSelection(Pos(4, 5), Pos(6, 5));130eqPos(cm.getCursor("head"), Pos(6, 5));131eqPos(cm.getCursor("anchor"), Pos(4, 5));132cm.setExtending(false);133cm.extendSelection(Pos(0, 3), Pos(0, 4));134eqPos(cm.getCursor("head"), Pos(0, 4));135eqPos(cm.getCursor("anchor"), Pos(0, 3));136});137138testCM("lines", function(cm) {139eq(cm.getLine(0), "111111");140eq(cm.getLine(1), "222222");141eq(cm.getLine(-1), null);142cm.removeLine(1);143cm.setLine(1, "abc");144eq(cm.getValue(), "111111\nabc");145}, {value: "111111\n222222\n333333"});146147testCM("indent", function(cm) {148cm.indentLine(1);149eq(cm.getLine(1), " blah();");150cm.setOption("indentUnit", 8);151cm.indentLine(1);152eq(cm.getLine(1), "\tblah();");153cm.setOption("indentUnit", 10);154cm.setOption("tabSize", 4);155cm.indentLine(1);156eq(cm.getLine(1), "\t\t blah();");157}, {value: "if (x) {\nblah();\n}", indentUnit: 3, indentWithTabs: true, tabSize: 8});158159testCM("indentByNumber", function(cm) {160cm.indentLine(0, 2);161eq(cm.getLine(0), " foo");162cm.indentLine(0, -200);163eq(cm.getLine(0), "foo");164cm.setSelection(Pos(0, 0), Pos(1, 2));165cm.indentSelection(3);166eq(cm.getValue(), " foo\n bar\nbaz");167}, {value: "foo\nbar\nbaz"});168169test("core_defaults", function() {170var defsCopy = {}, defs = CodeMirror.defaults;171for (var opt in defs) defsCopy[opt] = defs[opt];172defs.indentUnit = 5;173defs.value = "uu";174defs.enterMode = "keep";175defs.tabindex = 55;176var place = document.getElementById("testground"), cm = CodeMirror(place);177try {178eq(cm.getOption("indentUnit"), 5);179cm.setOption("indentUnit", 10);180eq(defs.indentUnit, 5);181eq(cm.getValue(), "uu");182eq(cm.getOption("enterMode"), "keep");183eq(cm.getInputField().tabIndex, 55);184}185finally {186for (var opt in defsCopy) defs[opt] = defsCopy[opt];187place.removeChild(cm.getWrapperElement());188}189});190191testCM("lineInfo", function(cm) {192eq(cm.lineInfo(-1), null);193var mark = document.createElement("span");194var lh = cm.setGutterMarker(1, "FOO", mark);195var info = cm.lineInfo(1);196eq(info.text, "222222");197eq(info.gutterMarkers.FOO, mark);198eq(info.line, 1);199eq(cm.lineInfo(2).gutterMarkers, null);200cm.setGutterMarker(lh, "FOO", null);201eq(cm.lineInfo(1).gutterMarkers, null);202cm.setGutterMarker(1, "FOO", mark);203cm.setGutterMarker(0, "FOO", mark);204cm.clearGutter("FOO");205eq(cm.lineInfo(0).gutterMarkers, null);206eq(cm.lineInfo(1).gutterMarkers, null);207}, {value: "111111\n222222\n333333"});208209testCM("coords", function(cm) {210cm.setSize(null, 100);211addDoc(cm, 32, 200);212var top = cm.charCoords(Pos(0, 0));213var bot = cm.charCoords(Pos(200, 30));214is(top.left < bot.left);215is(top.top < bot.top);216is(top.top < top.bottom);217cm.scrollTo(null, 100);218var top2 = cm.charCoords(Pos(0, 0));219is(top.top > top2.top);220eq(top.left, top2.left);221});222223testCM("coordsChar", function(cm) {224addDoc(cm, 35, 70);225for (var i = 0; i < 2; ++i) {226var sys = i ? "local" : "page";227for (var ch = 0; ch <= 35; ch += 5) {228for (var line = 0; line < 70; line += 5) {229cm.setCursor(line, ch);230var coords = cm.charCoords(Pos(line, ch), sys);231var pos = cm.coordsChar({left: coords.left + 1, top: coords.top + 1}, sys);232eqPos(pos, Pos(line, ch));233}234}235}236}, {lineNumbers: true});237238testCM("posFromIndex", function(cm) {239cm.setValue(240"This function should\n" +241"convert a zero based index\n" +242"to line and ch."243);244245var examples = [246{ index: -1, line: 0, ch: 0 }, // <- Tests clipping247{ index: 0, line: 0, ch: 0 },248{ index: 10, line: 0, ch: 10 },249{ index: 39, line: 1, ch: 18 },250{ index: 55, line: 2, ch: 7 },251{ index: 63, line: 2, ch: 15 },252{ index: 64, line: 2, ch: 15 } // <- Tests clipping253];254255for (var i = 0; i < examples.length; i++) {256var example = examples[i];257var pos = cm.posFromIndex(example.index);258eq(pos.line, example.line);259eq(pos.ch, example.ch);260if (example.index >= 0 && example.index < 64)261eq(cm.indexFromPos(pos), example.index);262}263});264265testCM("undo", function(cm) {266cm.setLine(0, "def");267eq(cm.historySize().undo, 1);268cm.undo();269eq(cm.getValue(), "abc");270eq(cm.historySize().undo, 0);271eq(cm.historySize().redo, 1);272cm.redo();273eq(cm.getValue(), "def");274eq(cm.historySize().undo, 1);275eq(cm.historySize().redo, 0);276cm.setValue("1\n\n\n2");277cm.clearHistory();278eq(cm.historySize().undo, 0);279for (var i = 0; i < 20; ++i) {280cm.replaceRange("a", Pos(0, 0));281cm.replaceRange("b", Pos(3, 0));282}283eq(cm.historySize().undo, 40);284for (var i = 0; i < 40; ++i)285cm.undo();286eq(cm.historySize().redo, 40);287eq(cm.getValue(), "1\n\n\n2");288}, {value: "abc"});289290testCM("undoDepth", function(cm) {291cm.replaceRange("d", Pos(0));292cm.replaceRange("e", Pos(0));293cm.replaceRange("f", Pos(0));294cm.undo(); cm.undo(); cm.undo();295eq(cm.getValue(), "abcd");296}, {value: "abc", undoDepth: 2});297298testCM("undoDoesntClearValue", function(cm) {299cm.undo();300eq(cm.getValue(), "x");301}, {value: "x"});302303testCM("undoMultiLine", function(cm) {304cm.operation(function() {305cm.replaceRange("x", Pos(0, 0));306cm.replaceRange("y", Pos(1, 0));307});308cm.undo();309eq(cm.getValue(), "abc\ndef\nghi");310cm.operation(function() {311cm.replaceRange("y", Pos(1, 0));312cm.replaceRange("x", Pos(0, 0));313});314cm.undo();315eq(cm.getValue(), "abc\ndef\nghi");316cm.operation(function() {317cm.replaceRange("y", Pos(2, 0));318cm.replaceRange("x", Pos(1, 0));319cm.replaceRange("z", Pos(2, 0));320});321cm.undo();322eq(cm.getValue(), "abc\ndef\nghi", 3);323}, {value: "abc\ndef\nghi"});324325testCM("undoComposite", function(cm) {326cm.replaceRange("y", Pos(1));327cm.operation(function() {328cm.replaceRange("x", Pos(0));329cm.replaceRange("z", Pos(2));330});331eq(cm.getValue(), "ax\nby\ncz\n");332cm.undo();333eq(cm.getValue(), "a\nby\nc\n");334cm.undo();335eq(cm.getValue(), "a\nb\nc\n");336cm.redo(); cm.redo();337eq(cm.getValue(), "ax\nby\ncz\n");338}, {value: "a\nb\nc\n"});339340testCM("undoSelection", function(cm) {341cm.setSelection(Pos(0, 2), Pos(0, 4));342cm.replaceSelection("");343cm.setCursor(Pos(1, 0));344cm.undo();345eqPos(cm.getCursor(true), Pos(0, 2));346eqPos(cm.getCursor(false), Pos(0, 4));347cm.setCursor(Pos(1, 0));348cm.redo();349eqPos(cm.getCursor(true), Pos(0, 2));350eqPos(cm.getCursor(false), Pos(0, 2));351}, {value: "abcdefgh\n"});352353testCM("markTextSingleLine", function(cm) {354forEach([{a: 0, b: 1, c: "", f: 2, t: 5},355{a: 0, b: 4, c: "", f: 0, t: 2},356{a: 1, b: 2, c: "x", f: 3, t: 6},357{a: 4, b: 5, c: "", f: 3, t: 5},358{a: 4, b: 5, c: "xx", f: 3, t: 7},359{a: 2, b: 5, c: "", f: 2, t: 3},360{a: 2, b: 5, c: "abcd", f: 6, t: 7},361{a: 2, b: 6, c: "x", f: null, t: null},362{a: 3, b: 6, c: "", f: null, t: null},363{a: 0, b: 9, c: "hallo", f: null, t: null},364{a: 4, b: 6, c: "x", f: 3, t: 4},365{a: 4, b: 8, c: "", f: 3, t: 4},366{a: 6, b: 6, c: "a", f: 3, t: 6},367{a: 8, b: 9, c: "", f: 3, t: 6}], function(test) {368cm.setValue("1234567890");369var r = cm.markText(Pos(0, 3), Pos(0, 6), {className: "foo"});370cm.replaceRange(test.c, Pos(0, test.a), Pos(0, test.b));371var f = r.find();372eq(f && f.from.ch, test.f); eq(f && f.to.ch, test.t);373});374});375376testCM("markTextMultiLine", function(cm) {377function p(v) { return v && Pos(v[0], v[1]); }378forEach([{a: [0, 0], b: [0, 5], c: "", f: [0, 0], t: [2, 5]},379{a: [0, 0], b: [0, 5], c: "foo\n", f: [1, 0], t: [3, 5]},380{a: [0, 1], b: [0, 10], c: "", f: [0, 1], t: [2, 5]},381{a: [0, 5], b: [0, 6], c: "x", f: [0, 6], t: [2, 5]},382{a: [0, 0], b: [1, 0], c: "", f: [0, 0], t: [1, 5]},383{a: [0, 6], b: [2, 4], c: "", f: [0, 5], t: [0, 7]},384{a: [0, 6], b: [2, 4], c: "aa", f: [0, 5], t: [0, 9]},385{a: [1, 2], b: [1, 8], c: "", f: [0, 5], t: [2, 5]},386{a: [0, 5], b: [2, 5], c: "xx", f: null, t: null},387{a: [0, 0], b: [2, 10], c: "x", f: null, t: null},388{a: [1, 5], b: [2, 5], c: "", f: [0, 5], t: [1, 5]},389{a: [2, 0], b: [2, 3], c: "", f: [0, 5], t: [2, 2]},390{a: [2, 5], b: [3, 0], c: "a\nb", f: [0, 5], t: [2, 5]},391{a: [2, 3], b: [3, 0], c: "x", f: [0, 5], t: [2, 3]},392{a: [1, 1], b: [1, 9], c: "1\n2\n3", f: [0, 5], t: [4, 5]}], function(test) {393cm.setValue("aaaaaaaaaa\nbbbbbbbbbb\ncccccccccc\ndddddddd\n");394var r = cm.markText(Pos(0, 5), Pos(2, 5),395{className: "CodeMirror-matchingbracket"});396cm.replaceRange(test.c, p(test.a), p(test.b));397var f = r.find();398eqPos(f && f.from, p(test.f)); eqPos(f && f.to, p(test.t));399});400});401402testCM("markTextUndo", function(cm) {403var marker1, marker2, bookmark;404marker1 = cm.markText(Pos(0, 1), Pos(0, 3),405{className: "CodeMirror-matchingbracket"});406marker2 = cm.markText(Pos(0, 0), Pos(2, 1),407{className: "CodeMirror-matchingbracket"});408bookmark = cm.setBookmark(Pos(1, 5));409cm.operation(function(){410cm.replaceRange("foo", Pos(0, 2));411cm.replaceRange("bar\nbaz\nbug\n", Pos(2, 0), Pos(3, 0));412});413var v1 = cm.getValue();414cm.setValue("");415eq(marker1.find(), null); eq(marker2.find(), null); eq(bookmark.find(), null);416cm.undo();417eqPos(bookmark.find(), Pos(1, 5), "still there");418cm.undo();419var m1Pos = marker1.find(), m2Pos = marker2.find();420eqPos(m1Pos.from, Pos(0, 1)); eqPos(m1Pos.to, Pos(0, 3));421eqPos(m2Pos.from, Pos(0, 0)); eqPos(m2Pos.to, Pos(2, 1));422eqPos(bookmark.find(), Pos(1, 5));423cm.redo(); cm.redo();424eq(bookmark.find(), null);425cm.undo();426eqPos(bookmark.find(), Pos(1, 5));427eq(cm.getValue(), v1);428}, {value: "1234\n56789\n00\n"});429430testCM("markTextStayGone", function(cm) {431var m1 = cm.markText(Pos(0, 0), Pos(0, 1));432cm.replaceRange("hi", Pos(0, 2));433m1.clear();434cm.undo();435eq(m1.find(), null);436}, {value: "hello"});437438testCM("markTextAllowEmpty", function(cm) {439var m1 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false});440is(m1.find());441cm.replaceRange("x", Pos(0, 0));442is(m1.find());443cm.replaceRange("y", Pos(0, 2));444is(m1.find());445cm.replaceRange("z", Pos(0, 3), Pos(0, 4));446is(!m1.find());447var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false,448inclusiveLeft: true,449inclusiveRight: true});450cm.replaceRange("q", Pos(0, 1), Pos(0, 2));451is(m2.find());452cm.replaceRange("", Pos(0, 0), Pos(0, 3));453is(!m2.find());454var m3 = cm.markText(Pos(0, 1), Pos(0, 1), {clearWhenEmpty: false});455cm.replaceRange("a", Pos(0, 3));456is(m3.find());457cm.replaceRange("b", Pos(0, 1));458is(!m3.find());459}, {value: "abcde"});460461testCM("markTextStacked", function(cm) {462var m1 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false});463var m2 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false});464cm.replaceRange("B", Pos(0, 1));465is(m1.find() && m2.find());466}, {value: "A"});467468testCM("undoPreservesNewMarks", function(cm) {469cm.markText(Pos(0, 3), Pos(0, 4));470cm.markText(Pos(1, 1), Pos(1, 3));471cm.replaceRange("", Pos(0, 3), Pos(3, 1));472var mBefore = cm.markText(Pos(0, 0), Pos(0, 1));473var mAfter = cm.markText(Pos(0, 5), Pos(0, 6));474var mAround = cm.markText(Pos(0, 2), Pos(0, 4));475cm.undo();476eqPos(mBefore.find().from, Pos(0, 0));477eqPos(mBefore.find().to, Pos(0, 1));478eqPos(mAfter.find().from, Pos(3, 3));479eqPos(mAfter.find().to, Pos(3, 4));480eqPos(mAround.find().from, Pos(0, 2));481eqPos(mAround.find().to, Pos(3, 2));482var found = cm.findMarksAt(Pos(2, 2));483eq(found.length, 1);484eq(found[0], mAround);485}, {value: "aaaa\nbbbb\ncccc\ndddd"});486487testCM("markClearBetween", function(cm) {488cm.setValue("aaa\nbbb\nccc\nddd\n");489cm.markText(Pos(0, 0), Pos(2));490cm.replaceRange("aaa\nbbb\nccc", Pos(0, 0), Pos(2));491eq(cm.findMarksAt(Pos(1, 1)).length, 0);492});493494testCM("deleteSpanCollapsedInclusiveLeft", function(cm) {495var from = Pos(1, 0), to = Pos(1, 1);496var m = cm.markText(from, to, {collapsed: true, inclusiveLeft: true});497// Delete collapsed span.498cm.replaceRange("", from, to);499}, {value: "abc\nX\ndef"});500501testCM("bookmark", function(cm) {502function p(v) { return v && Pos(v[0], v[1]); }503forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]},504{a: [1, 1], b: [1, 1], c: "xx", d: [1, 7]},505{a: [1, 4], b: [1, 5], c: "ab", d: [1, 6]},506{a: [1, 4], b: [1, 6], c: "", d: null},507{a: [1, 5], b: [1, 6], c: "abc", d: [1, 5]},508{a: [1, 6], b: [1, 8], c: "", d: [1, 5]},509{a: [1, 4], b: [1, 4], c: "\n\n", d: [3, 1]},510{bm: [1, 9], a: [1, 1], b: [1, 1], c: "\n", d: [2, 8]}], function(test) {511cm.setValue("1234567890\n1234567890\n1234567890");512var b = cm.setBookmark(p(test.bm) || Pos(1, 5));513cm.replaceRange(test.c, p(test.a), p(test.b));514eqPos(b.find(), p(test.d));515});516});517518testCM("bookmarkInsertLeft", function(cm) {519var br = cm.setBookmark(Pos(0, 2), {insertLeft: false});520var bl = cm.setBookmark(Pos(0, 2), {insertLeft: true});521cm.setCursor(Pos(0, 2));522cm.replaceSelection("hi");523eqPos(br.find(), Pos(0, 2));524eqPos(bl.find(), Pos(0, 4));525cm.replaceRange("", Pos(0, 4), Pos(0, 5));526cm.replaceRange("", Pos(0, 2), Pos(0, 4));527cm.replaceRange("", Pos(0, 1), Pos(0, 2));528// Verify that deleting next to bookmarks doesn't kill them529eqPos(br.find(), Pos(0, 1));530eqPos(bl.find(), Pos(0, 1));531}, {value: "abcdef"});532533testCM("bookmarkCursor", function(cm) {534var pos01 = cm.cursorCoords(Pos(0, 1)), pos11 = cm.cursorCoords(Pos(1, 1)),535pos20 = cm.cursorCoords(Pos(2, 0)), pos30 = cm.cursorCoords(Pos(3, 0)),536pos41 = cm.cursorCoords(Pos(4, 1));537cm.setBookmark(Pos(0, 1), {widget: document.createTextNode("←"), insertLeft: true});538cm.setBookmark(Pos(2, 0), {widget: document.createTextNode("←"), insertLeft: true});539cm.setBookmark(Pos(1, 1), {widget: document.createTextNode("→")});540cm.setBookmark(Pos(3, 0), {widget: document.createTextNode("→")});541var new01 = cm.cursorCoords(Pos(0, 1)), new11 = cm.cursorCoords(Pos(1, 1)),542new20 = cm.cursorCoords(Pos(2, 0)), new30 = cm.cursorCoords(Pos(3, 0));543is(new01.left == pos01.left && new01.top == pos01.top, "at left, middle of line");544is(new11.left > pos11.left && new11.top == pos11.top, "at right, middle of line");545is(new20.left == pos20.left && new20.top == pos20.top, "at left, empty line");546is(new30.left > pos30.left && new30.top == pos30.top, "at right, empty line");547cm.setBookmark(Pos(4, 0), {widget: document.createTextNode("→")});548is(cm.cursorCoords(Pos(4, 1)).left > pos41.left, "single-char bug");549}, {value: "foo\nbar\n\n\nx\ny"});550551testCM("multiBookmarkCursor", function(cm) {552if (phantom) return;553var ms = [], m;554function add(insertLeft) {555for (var i = 0; i < 3; ++i) {556var node = document.createElement("span");557node.innerHTML = "X";558ms.push(cm.setBookmark(Pos(0, 1), {widget: node, insertLeft: insertLeft}));559}560}561var base1 = cm.cursorCoords(Pos(0, 1)).left, base4 = cm.cursorCoords(Pos(0, 4)).left;562add(true);563is(Math.abs(base1 - cm.cursorCoords(Pos(0, 1)).left) < .1);564while (m = ms.pop()) m.clear();565add(false);566is(Math.abs(base4 - cm.cursorCoords(Pos(0, 1)).left) < .1);567}, {value: "abcdefg"});568569testCM("getAllMarks", function(cm) {570addDoc(cm, 10, 10);571var m1 = cm.setBookmark(Pos(0, 2));572var m2 = cm.markText(Pos(0, 2), Pos(3, 2));573var m3 = cm.markText(Pos(1, 2), Pos(1, 8));574var m4 = cm.markText(Pos(8, 0), Pos(9, 0));575eq(cm.getAllMarks().length, 4);576m1.clear();577m3.clear();578eq(cm.getAllMarks().length, 2);579});580581testCM("bug577", function(cm) {582cm.setValue("a\nb");583cm.clearHistory();584cm.setValue("fooooo");585cm.undo();586});587588testCM("scrollSnap", function(cm) {589cm.setSize(100, 100);590addDoc(cm, 200, 200);591cm.setCursor(Pos(100, 180));592var info = cm.getScrollInfo();593is(info.left > 0 && info.top > 0);594cm.setCursor(Pos(0, 0));595info = cm.getScrollInfo();596is(info.left == 0 && info.top == 0, "scrolled clean to top");597cm.setCursor(Pos(100, 180));598cm.setCursor(Pos(199, 0));599info = cm.getScrollInfo();600is(info.left == 0 && info.top + 2 > info.height - cm.getScrollerElement().clientHeight, "scrolled clean to bottom");601});602603testCM("scrollIntoView", function(cm) {604if (phantom) return;605var outer = cm.getWrapperElement().getBoundingClientRect();606function test(line, ch) {607var pos = Pos(line, ch);608cm.scrollIntoView(pos);609var box = cm.charCoords(pos, "window");610is(box.left >= outer.left && box.right <= outer.right &&611box.top >= outer.top && box.bottom <= outer.bottom);612}613addDoc(cm, 200, 200);614test(199, 199);615test(0, 0);616test(100, 100);617test(199, 0);618test(0, 199);619test(100, 100);620});621622testCM("selectionPos", function(cm) {623if (phantom) return;624cm.setSize(100, 100);625addDoc(cm, 200, 100);626cm.setSelection(Pos(1, 100), Pos(98, 100));627var lineWidth = cm.charCoords(Pos(0, 200), "local").left;628var lineHeight = (cm.charCoords(Pos(99)).top - cm.charCoords(Pos(0)).top) / 100;629cm.scrollTo(0, 0);630var selElt = byClassName(cm.getWrapperElement(), "CodeMirror-selected");631var outer = cm.getWrapperElement().getBoundingClientRect();632var sawMiddle, sawTop, sawBottom;633for (var i = 0, e = selElt.length; i < e; ++i) {634var box = selElt[i].getBoundingClientRect();635var atLeft = box.left - outer.left < 30;636var width = box.right - box.left;637var atRight = box.right - outer.left > .8 * lineWidth;638if (atLeft && atRight) {639sawMiddle = true;640is(box.bottom - box.top > 90 * lineHeight, "middle high");641is(width > .9 * lineWidth, "middle wide");642} else {643is(width > .4 * lineWidth, "top/bot wide enough");644is(width < .6 * lineWidth, "top/bot slim enough");645if (atLeft) {646sawBottom = true;647is(box.top - outer.top > 96 * lineHeight, "bot below");648} else if (atRight) {649sawTop = true;650is(box.top - outer.top < 2.1 * lineHeight, "top above");651}652}653}654is(sawTop && sawBottom && sawMiddle, "all parts");655}, null);656657testCM("restoreHistory", function(cm) {658cm.setValue("abc\ndef");659cm.setLine(1, "hello");660cm.setLine(0, "goop");661cm.undo();662var storedVal = cm.getValue(), storedHist = cm.getHistory();663if (window.JSON) storedHist = JSON.parse(JSON.stringify(storedHist));664eq(storedVal, "abc\nhello");665cm.setValue("");666cm.clearHistory();667eq(cm.historySize().undo, 0);668cm.setValue(storedVal);669cm.setHistory(storedHist);670cm.redo();671eq(cm.getValue(), "goop\nhello");672cm.undo(); cm.undo();673eq(cm.getValue(), "abc\ndef");674});675676testCM("doubleScrollbar", function(cm) {677var dummy = document.body.appendChild(document.createElement("p"));678dummy.style.cssText = "height: 50px; overflow: scroll; width: 50px";679var scrollbarWidth = dummy.offsetWidth + 1 - dummy.clientWidth;680document.body.removeChild(dummy);681if (scrollbarWidth < 2) return;682cm.setSize(null, 100);683addDoc(cm, 1, 300);684var wrap = cm.getWrapperElement();685is(wrap.offsetWidth - byClassName(wrap, "CodeMirror-lines")[0].offsetWidth <= scrollbarWidth * 1.5);686});687688testCM("weirdLinebreaks", function(cm) {689cm.setValue("foo\nbar\rbaz\r\nquux\n\rplop");690is(cm.getValue(), "foo\nbar\nbaz\nquux\n\nplop");691is(cm.lineCount(), 6);692cm.setValue("\n\n");693is(cm.lineCount(), 3);694});695696testCM("setSize", function(cm) {697cm.setSize(100, 100);698var wrap = cm.getWrapperElement();699is(wrap.offsetWidth, 100);700is(wrap.offsetHeight, 100);701cm.setSize("100%", "3em");702is(wrap.style.width, "100%");703is(wrap.style.height, "3em");704cm.setSize(null, 40);705is(wrap.style.width, "100%");706is(wrap.style.height, "40px");707});708709function foldLines(cm, start, end, autoClear) {710return cm.markText(Pos(start, 0), Pos(end - 1), {711inclusiveLeft: true,712inclusiveRight: true,713collapsed: true,714clearOnEnter: autoClear715});716}717718testCM("collapsedLines", function(cm) {719addDoc(cm, 4, 10);720var range = foldLines(cm, 4, 5), cleared = 0;721CodeMirror.on(range, "clear", function() {cleared++;});722cm.setCursor(Pos(3, 0));723CodeMirror.commands.goLineDown(cm);724eqPos(cm.getCursor(), Pos(5, 0));725cm.setLine(3, "abcdefg");726cm.setCursor(Pos(3, 6));727CodeMirror.commands.goLineDown(cm);728eqPos(cm.getCursor(), Pos(5, 4));729cm.setLine(3, "ab");730cm.setCursor(Pos(3, 2));731CodeMirror.commands.goLineDown(cm);732eqPos(cm.getCursor(), Pos(5, 2));733cm.operation(function() {range.clear(); range.clear();});734eq(cleared, 1);735});736737testCM("collapsedRangeCoordsChar", function(cm) {738var pos_1_3 = cm.charCoords(Pos(1, 3));739pos_1_3.left += 2; pos_1_3.top += 2;740var opts = {collapsed: true, inclusiveLeft: true, inclusiveRight: true};741var m1 = cm.markText(Pos(0, 0), Pos(2, 0), opts);742eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));743m1.clear();744var m1 = cm.markText(Pos(0, 0), Pos(1, 1), {collapsed: true, inclusiveLeft: true});745var m2 = cm.markText(Pos(1, 1), Pos(2, 0), {collapsed: true, inclusiveRight: true});746eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));747m1.clear(); m2.clear();748var m1 = cm.markText(Pos(0, 0), Pos(1, 6), opts);749eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));750}, {value: "123456\nabcdef\nghijkl\nmnopqr\n"});751752testCM("hiddenLinesAutoUnfold", function(cm) {753var range = foldLines(cm, 1, 3, true), cleared = 0;754CodeMirror.on(range, "clear", function() {cleared++;});755cm.setCursor(Pos(3, 0));756eq(cleared, 0);757cm.execCommand("goCharLeft");758eq(cleared, 1);759range = foldLines(cm, 1, 3, true);760CodeMirror.on(range, "clear", function() {cleared++;});761eqPos(cm.getCursor(), Pos(3, 0));762cm.setCursor(Pos(0, 3));763cm.execCommand("goCharRight");764eq(cleared, 2);765}, {value: "abc\ndef\nghi\njkl"});766767testCM("hiddenLinesSelectAll", function(cm) { // Issue #484768addDoc(cm, 4, 20);769foldLines(cm, 0, 10);770foldLines(cm, 11, 20);771CodeMirror.commands.selectAll(cm);772eqPos(cm.getCursor(true), Pos(10, 0));773eqPos(cm.getCursor(false), Pos(10, 4));774});775776777testCM("everythingFolded", function(cm) {778addDoc(cm, 2, 2);779function enterPress() {780cm.triggerOnKeyDown({type: "keydown", keyCode: 13, preventDefault: function(){}, stopPropagation: function(){}});781}782var fold = foldLines(cm, 0, 2);783enterPress();784eq(cm.getValue(), "xx\nxx");785fold.clear();786fold = foldLines(cm, 0, 2, true);787eq(fold.find(), null);788enterPress();789eq(cm.getValue(), "\nxx\nxx");790});791792testCM("structuredFold", function(cm) {793if (phantom) return;794addDoc(cm, 4, 8);795var range = cm.markText(Pos(1, 2), Pos(6, 2), {796replacedWith: document.createTextNode("Q")797});798cm.setCursor(0, 3);799CodeMirror.commands.goLineDown(cm);800eqPos(cm.getCursor(), Pos(6, 2));801CodeMirror.commands.goCharLeft(cm);802eqPos(cm.getCursor(), Pos(1, 2));803CodeMirror.commands.delCharAfter(cm);804eq(cm.getValue(), "xxxx\nxxxx\nxxxx");805addDoc(cm, 4, 8);806range = cm.markText(Pos(1, 2), Pos(6, 2), {807replacedWith: document.createTextNode("M"),808clearOnEnter: true809});810var cleared = 0;811CodeMirror.on(range, "clear", function(){++cleared;});812cm.setCursor(0, 3);813CodeMirror.commands.goLineDown(cm);814eqPos(cm.getCursor(), Pos(6, 2));815CodeMirror.commands.goCharLeft(cm);816eqPos(cm.getCursor(), Pos(6, 1));817eq(cleared, 1);818range.clear();819eq(cleared, 1);820range = cm.markText(Pos(1, 2), Pos(6, 2), {821replacedWith: document.createTextNode("Q"),822clearOnEnter: true823});824range.clear();825cm.setCursor(1, 2);826CodeMirror.commands.goCharRight(cm);827eqPos(cm.getCursor(), Pos(1, 3));828range = cm.markText(Pos(2, 0), Pos(4, 4), {829replacedWith: document.createTextNode("M")830});831cm.setCursor(1, 0);832CodeMirror.commands.goLineDown(cm);833eqPos(cm.getCursor(), Pos(2, 0));834}, null);835836testCM("nestedFold", function(cm) {837addDoc(cm, 10, 3);838function fold(ll, cl, lr, cr) {839return cm.markText(Pos(ll, cl), Pos(lr, cr), {collapsed: true});840}841var inner1 = fold(0, 6, 1, 3), inner2 = fold(0, 2, 1, 8), outer = fold(0, 1, 2, 3), inner0 = fold(0, 5, 0, 6);842cm.setCursor(0, 1);843CodeMirror.commands.goCharRight(cm);844eqPos(cm.getCursor(), Pos(2, 3));845inner0.clear();846CodeMirror.commands.goCharLeft(cm);847eqPos(cm.getCursor(), Pos(0, 1));848outer.clear();849CodeMirror.commands.goCharRight(cm);850eqPos(cm.getCursor(), Pos(0, 2));851CodeMirror.commands.goCharRight(cm);852eqPos(cm.getCursor(), Pos(1, 8));853inner2.clear();854CodeMirror.commands.goCharLeft(cm);855eqPos(cm.getCursor(), Pos(1, 7));856cm.setCursor(0, 5);857CodeMirror.commands.goCharRight(cm);858eqPos(cm.getCursor(), Pos(0, 6));859CodeMirror.commands.goCharRight(cm);860eqPos(cm.getCursor(), Pos(1, 3));861});862863testCM("badNestedFold", function(cm) {864addDoc(cm, 4, 4);865cm.markText(Pos(0, 2), Pos(3, 2), {collapsed: true});866var caught;867try {cm.markText(Pos(0, 1), Pos(0, 3), {collapsed: true});}868catch(e) {caught = e;}869is(caught instanceof Error, "no error");870is(/overlap/i.test(caught.message), "wrong error");871});872873testCM("nestedFoldOnSide", function(cm) {874var m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true, inclusiveRight: true});875var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true});876cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true}).clear();877try { cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true, inclusiveLeft: true}); }878catch(e) { var caught = e; }879is(caught && /overlap/i.test(caught.message));880var m3 = cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true});881var m4 = cm.markText(Pos(2, 0), Pos(2, 1), {collapse: true, inclusiveRight: true});882m1.clear(); m4.clear();883m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true});884cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true}).clear();885try { cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true, inclusiveRight: true}); }886catch(e) { var caught = e; }887is(caught && /overlap/i.test(caught.message));888}, {value: "ab\ncd\ef"});889890testCM("wrappingInlineWidget", function(cm) {891cm.setSize("11em");892var w = document.createElement("span");893w.style.color = "red";894w.innerHTML = "one two three four";895cm.markText(Pos(0, 6), Pos(0, 9), {replacedWith: w});896var cur0 = cm.cursorCoords(Pos(0, 0)), cur1 = cm.cursorCoords(Pos(0, 10));897is(cur0.top < cur1.top);898is(cur0.bottom < cur1.bottom);899var curL = cm.cursorCoords(Pos(0, 6)), curR = cm.cursorCoords(Pos(0, 9));900eq(curL.top, cur0.top);901eq(curL.bottom, cur0.bottom);902eq(curR.top, cur1.top);903eq(curR.bottom, cur1.bottom);904cm.replaceRange("", Pos(0, 9), Pos(0));905curR = cm.cursorCoords(Pos(0, 9));906eq(curR.top, cur1.top);907eq(curR.bottom, cur1.bottom);908}, {value: "1 2 3 xxx 4", lineWrapping: true});909910testCM("changedInlineWidget", function(cm) {911cm.setSize("10em");912var w = document.createElement("span");913w.innerHTML = "x";914var m = cm.markText(Pos(0, 4), Pos(0, 5), {replacedWith: w});915w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";916m.changed();917var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];918is(hScroll.scrollWidth > hScroll.clientWidth);919}, {value: "hello there"});920921testCM("changedBookmark", function(cm) {922cm.setSize("10em");923var w = document.createElement("span");924w.innerHTML = "x";925var m = cm.setBookmark(Pos(0, 4), {widget: w});926w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";927m.changed();928var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];929is(hScroll.scrollWidth > hScroll.clientWidth);930}, {value: "abcdefg"});931932testCM("inlineWidget", function(cm) {933var w = cm.setBookmark(Pos(0, 2), {widget: document.createTextNode("uu")});934cm.setCursor(0, 2);935CodeMirror.commands.goLineDown(cm);936eqPos(cm.getCursor(), Pos(1, 4));937cm.setCursor(0, 2);938cm.replaceSelection("hi");939eqPos(w.find(), Pos(0, 2));940cm.setCursor(0, 1);941cm.replaceSelection("ay");942eqPos(w.find(), Pos(0, 4));943eq(cm.getLine(0), "uayuhiuu");944}, {value: "uuuu\nuuuuuu"});945946testCM("wrappingAndResizing", function(cm) {947cm.setSize(null, "auto");948cm.setOption("lineWrapping", true);949var wrap = cm.getWrapperElement(), h0 = wrap.offsetHeight;950var doc = "xxx xxx xxx xxx xxx";951cm.setValue(doc);952for (var step = 10, w = cm.charCoords(Pos(0, 18), "div").right;; w += step) {953cm.setSize(w);954if (wrap.offsetHeight <= h0 * (opera_lt10 ? 1.2 : 1.5)) {955if (step == 10) { w -= 10; step = 1; }956else break;957}958}959// Ensure that putting the cursor at the end of the maximally long960// line doesn't cause wrapping to happen.961cm.setCursor(Pos(0, doc.length));962eq(wrap.offsetHeight, h0);963cm.replaceSelection("x");964is(wrap.offsetHeight > h0, "wrapping happens");965// Now add a max-height and, in a document consisting of966// almost-wrapped lines, go over it so that a scrollbar appears.967cm.setValue(doc + "\n" + doc + "\n");968cm.getScrollerElement().style.maxHeight = "100px";969cm.replaceRange("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n!\n", Pos(2, 0));970forEach([Pos(0, doc.length), Pos(0, doc.length - 1),971Pos(0, 0), Pos(1, doc.length), Pos(1, doc.length - 1)],972function(pos) {973var coords = cm.charCoords(pos);974eqPos(pos, cm.coordsChar({left: coords.left + 2, top: coords.top + 5}));975});976}, null, ie_lt8);977978testCM("measureEndOfLine", function(cm) {979cm.setSize(null, "auto");980var inner = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild;981var lh = inner.offsetHeight;982for (var step = 10, w = cm.charCoords(Pos(0, 7), "div").right;; w += step) {983cm.setSize(w);984if (inner.offsetHeight < 2.5 * lh) {985if (step == 10) { w -= 10; step = 1; }986else break;987}988}989cm.setValue(cm.getValue() + "\n\n");990var endPos = cm.charCoords(Pos(0, 18), "local");991is(endPos.top > lh * .8, "not at top");992is(endPos.left > w - 20, "not at right");993endPos = cm.charCoords(Pos(0, 18));994eqPos(cm.coordsChar({left: endPos.left, top: endPos.top + 5}), Pos(0, 18));995}, {mode: "text/html", value: "<!-- foo barrr -->", lineWrapping: true}, ie_lt8 || opera_lt10);996997testCM("scrollVerticallyAndHorizontally", function(cm) {998cm.setSize(100, 100);999addDoc(cm, 40, 40);1000cm.setCursor(39);1001var wrap = cm.getWrapperElement(), bar = byClassName(wrap, "CodeMirror-vscrollbar")[0];1002is(bar.offsetHeight < wrap.offsetHeight, "vertical scrollbar limited by horizontal one");1003var cursorBox = byClassName(wrap, "CodeMirror-cursor")[0].getBoundingClientRect();1004var editorBox = wrap.getBoundingClientRect();1005is(cursorBox.bottom < editorBox.top + cm.getScrollerElement().clientHeight,1006"bottom line visible");1007}, {lineNumbers: true});10081009testCM("moveVstuck", function(cm) {1010var lines = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild, h0 = lines.offsetHeight;1011var val = "fooooooooooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar\n";1012cm.setValue(val);1013for (var w = cm.charCoords(Pos(0, 26), "div").right * 2.8;; w += 5) {1014cm.setSize(w);1015if (lines.offsetHeight <= 3.5 * h0) break;1016}1017cm.setCursor(Pos(0, val.length - 1));1018cm.moveV(-1, "line");1019eqPos(cm.getCursor(), Pos(0, 26));1020}, {lineWrapping: true}, ie_lt8 || opera_lt10);10211022testCM("collapseOnMove", function(cm) {1023cm.setSelection(Pos(0, 1), Pos(2, 4));1024cm.execCommand("goLineUp");1025is(!cm.somethingSelected());1026eqPos(cm.getCursor(), Pos(0, 1));1027cm.setSelection(Pos(0, 1), Pos(2, 4));1028cm.execCommand("goPageDown");1029is(!cm.somethingSelected());1030eqPos(cm.getCursor(), Pos(2, 4));1031cm.execCommand("goLineUp");1032cm.execCommand("goLineUp");1033eqPos(cm.getCursor(), Pos(0, 4));1034cm.setSelection(Pos(0, 1), Pos(2, 4));1035cm.execCommand("goCharLeft");1036is(!cm.somethingSelected());1037eqPos(cm.getCursor(), Pos(0, 1));1038}, {value: "aaaaa\nb\nccccc"});10391040testCM("clickTab", function(cm) {1041var p0 = cm.charCoords(Pos(0, 0));1042eqPos(cm.coordsChar({left: p0.left + 5, top: p0.top + 5}), Pos(0, 0));1043eqPos(cm.coordsChar({left: p0.right - 5, top: p0.top + 5}), Pos(0, 1));1044}, {value: "\t\n\n", lineWrapping: true, tabSize: 8});10451046testCM("verticalScroll", function(cm) {1047cm.setSize(100, 200);1048cm.setValue("foo\nbar\nbaz\n");1049var sc = cm.getScrollerElement(), baseWidth = sc.scrollWidth;1050cm.setLine(0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah");1051is(sc.scrollWidth > baseWidth, "scrollbar present");1052cm.setLine(0, "foo");1053if (!phantom) eq(sc.scrollWidth, baseWidth, "scrollbar gone");1054cm.setLine(0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah");1055cm.setLine(1, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbh");1056is(sc.scrollWidth > baseWidth, "present again");1057var curWidth = sc.scrollWidth;1058cm.setLine(0, "foo");1059is(sc.scrollWidth < curWidth, "scrollbar smaller");1060is(sc.scrollWidth > baseWidth, "but still present");1061});10621063testCM("extraKeys", function(cm) {1064var outcome;1065function fakeKey(expected, code, props) {1066if (typeof code == "string") code = code.charCodeAt(0);1067var e = {type: "keydown", keyCode: code, preventDefault: function(){}, stopPropagation: function(){}};1068if (props) for (var n in props) e[n] = props[n];1069outcome = null;1070cm.triggerOnKeyDown(e);1071eq(outcome, expected);1072}1073CodeMirror.commands.testCommand = function() {outcome = "tc";};1074CodeMirror.commands.goTestCommand = function() {outcome = "gtc";};1075cm.setOption("extraKeys", {"Shift-X": function() {outcome = "sx";},1076"X": function() {outcome = "x";},1077"Ctrl-Alt-U": function() {outcome = "cau";},1078"End": "testCommand",1079"Home": "goTestCommand",1080"Tab": false});1081fakeKey(null, "U");1082fakeKey("cau", "U", {ctrlKey: true, altKey: true});1083fakeKey(null, "U", {shiftKey: true, ctrlKey: true, altKey: true});1084fakeKey("x", "X");1085fakeKey("sx", "X", {shiftKey: true});1086fakeKey("tc", 35);1087fakeKey(null, 35, {shiftKey: true});1088fakeKey("gtc", 36);1089fakeKey("gtc", 36, {shiftKey: true});1090fakeKey(null, 9);1091}, null, window.opera && mac);10921093testCM("wordMovementCommands", function(cm) {1094cm.execCommand("goWordLeft");1095eqPos(cm.getCursor(), Pos(0, 0));1096cm.execCommand("goWordRight"); cm.execCommand("goWordRight");1097eqPos(cm.getCursor(), Pos(0, 7));1098cm.execCommand("goWordLeft");1099eqPos(cm.getCursor(), Pos(0, 5));1100cm.execCommand("goWordRight"); cm.execCommand("goWordRight");1101eqPos(cm.getCursor(), Pos(0, 12));1102cm.execCommand("goWordLeft");1103eqPos(cm.getCursor(), Pos(0, 9));1104cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); cm.execCommand("goWordRight");1105eqPos(cm.getCursor(), Pos(0, 24));1106cm.execCommand("goWordRight"); cm.execCommand("goWordRight");1107eqPos(cm.getCursor(), Pos(1, 9));1108cm.execCommand("goWordRight");1109eqPos(cm.getCursor(), Pos(1, 13));1110cm.execCommand("goWordRight"); cm.execCommand("goWordRight");1111eqPos(cm.getCursor(), Pos(2, 0));1112}, {value: "this is (the) firstline.\na foo12\u00e9\u00f8\u00d7bar\n"});11131114testCM("groupMovementCommands", function(cm) {1115cm.execCommand("goGroupLeft");1116eqPos(cm.getCursor(), Pos(0, 0));1117cm.execCommand("goGroupRight");1118eqPos(cm.getCursor(), Pos(0, 4));1119cm.execCommand("goGroupRight");1120eqPos(cm.getCursor(), Pos(0, 7));1121cm.execCommand("goGroupRight");1122eqPos(cm.getCursor(), Pos(0, 10));1123cm.execCommand("goGroupLeft");1124eqPos(cm.getCursor(), Pos(0, 7));1125cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");1126eqPos(cm.getCursor(), Pos(0, 15));1127cm.setCursor(Pos(0, 17));1128cm.execCommand("goGroupLeft");1129eqPos(cm.getCursor(), Pos(0, 16));1130cm.execCommand("goGroupLeft");1131eqPos(cm.getCursor(), Pos(0, 14));1132cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");1133eqPos(cm.getCursor(), Pos(0, 20));1134cm.execCommand("goGroupRight");1135eqPos(cm.getCursor(), Pos(1, 5));1136cm.execCommand("goGroupLeft"); cm.execCommand("goGroupLeft");1137eqPos(cm.getCursor(), Pos(1, 0));1138cm.execCommand("goGroupLeft");1139eqPos(cm.getCursor(), Pos(0, 16));1140}, {value: "booo ba---quux. ffff\n abc d"});11411142testCM("charMovementCommands", function(cm) {1143cm.execCommand("goCharLeft"); cm.execCommand("goColumnLeft");1144eqPos(cm.getCursor(), Pos(0, 0));1145cm.execCommand("goCharRight"); cm.execCommand("goCharRight");1146eqPos(cm.getCursor(), Pos(0, 2));1147cm.setCursor(Pos(1, 0));1148cm.execCommand("goColumnLeft");1149eqPos(cm.getCursor(), Pos(1, 0));1150cm.execCommand("goCharLeft");1151eqPos(cm.getCursor(), Pos(0, 5));1152cm.execCommand("goColumnRight");1153eqPos(cm.getCursor(), Pos(0, 5));1154cm.execCommand("goCharRight");1155eqPos(cm.getCursor(), Pos(1, 0));1156cm.execCommand("goLineEnd");1157eqPos(cm.getCursor(), Pos(1, 5));1158cm.execCommand("goLineStartSmart");1159eqPos(cm.getCursor(), Pos(1, 1));1160cm.execCommand("goLineStartSmart");1161eqPos(cm.getCursor(), Pos(1, 0));1162cm.setCursor(Pos(2, 0));1163cm.execCommand("goCharRight"); cm.execCommand("goColumnRight");1164eqPos(cm.getCursor(), Pos(2, 0));1165}, {value: "line1\n ine2\n"});11661167testCM("verticalMovementCommands", function(cm) {1168cm.execCommand("goLineUp");1169eqPos(cm.getCursor(), Pos(0, 0));1170cm.execCommand("goLineDown");1171if (!phantom) // This fails in PhantomJS, though not in a real Webkit1172eqPos(cm.getCursor(), Pos(1, 0));1173cm.setCursor(Pos(1, 12));1174cm.execCommand("goLineDown");1175eqPos(cm.getCursor(), Pos(2, 5));1176cm.execCommand("goLineDown");1177eqPos(cm.getCursor(), Pos(3, 0));1178cm.execCommand("goLineUp");1179eqPos(cm.getCursor(), Pos(2, 5));1180cm.execCommand("goLineUp");1181eqPos(cm.getCursor(), Pos(1, 12));1182cm.execCommand("goPageDown");1183eqPos(cm.getCursor(), Pos(5, 0));1184cm.execCommand("goPageDown"); cm.execCommand("goLineDown");1185eqPos(cm.getCursor(), Pos(5, 0));1186cm.execCommand("goPageUp");1187eqPos(cm.getCursor(), Pos(0, 0));1188}, {value: "line1\nlong long line2\nline3\n\nline5\n"});11891190testCM("verticalMovementCommandsWrapping", function(cm) {1191cm.setSize(120);1192cm.setCursor(Pos(0, 5));1193cm.execCommand("goLineDown");1194eq(cm.getCursor().line, 0);1195is(cm.getCursor().ch > 5, "moved beyond wrap");1196for (var i = 0; ; ++i) {1197is(i < 20, "no endless loop");1198cm.execCommand("goLineDown");1199var cur = cm.getCursor();1200if (cur.line == 1) eq(cur.ch, 5);1201if (cur.line == 2) { eq(cur.ch, 1); break; }1202}1203}, {value: "a very long line that wraps around somehow so that we can test cursor movement\nshortone\nk",1204lineWrapping: true});12051206testCM("rtlMovement", function(cm) {1207forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج",1208"خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر", "خ ة ق",1209"<img src=\"/בדיקה3.jpg\">"], function(line) {1210var inv = line.charAt(0) == "خ";1211cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart");1212var cursor = byClassName(cm.getWrapperElement(), "CodeMirror-cursor")[0];1213var prevX = cursor.offsetLeft, prevY = cursor.offsetTop;1214for (var i = 0; i <= line.length; ++i) {1215cm.execCommand("goCharRight");1216if (i == line.length) is(cursor.offsetTop > prevY, "next line");1217else is(cursor.offsetLeft > prevX, "moved right");1218prevX = cursor.offsetLeft; prevY = cursor.offsetTop;1219}1220cm.setCursor(0, 0); cm.execCommand(inv ? "goLineStart" : "goLineEnd");1221prevX = cursor.offsetLeft;1222for (var i = 0; i < line.length; ++i) {1223cm.execCommand("goCharLeft");1224is(cursor.offsetLeft < prevX, "moved left");1225prevX = cursor.offsetLeft;1226}1227});1228});12291230// Verify that updating a line clears its bidi ordering1231testCM("bidiUpdate", function(cm) {1232cm.setCursor(Pos(0, 2));1233cm.replaceSelection("خحج", "start");1234cm.execCommand("goCharRight");1235eqPos(cm.getCursor(), Pos(0, 4));1236}, {value: "abcd\n"});12371238testCM("movebyTextUnit", function(cm) {1239cm.setValue("בְּרֵאשִ\ńéée\n");1240cm.execCommand("goLineEnd");1241for (var i = 0; i < 4; ++i) cm.execCommand("goCharRight");1242eqPos(cm.getCursor(), Pos(0, 0));1243cm.execCommand("goCharRight");1244eqPos(cm.getCursor(), Pos(1, 0));1245cm.execCommand("goCharRight");1246cm.execCommand("goCharRight");1247eqPos(cm.getCursor(), Pos(1, 3));1248cm.execCommand("goCharRight");1249cm.execCommand("goCharRight");1250eqPos(cm.getCursor(), Pos(1, 6));1251});12521253testCM("lineChangeEvents", function(cm) {1254addDoc(cm, 3, 5);1255var log = [], want = ["ch 0", "ch 1", "del 2", "ch 0", "ch 0", "del 1", "del 3", "del 4"];1256for (var i = 0; i < 5; ++i) {1257CodeMirror.on(cm.getLineHandle(i), "delete", function(i) {1258return function() {log.push("del " + i);};1259}(i));1260CodeMirror.on(cm.getLineHandle(i), "change", function(i) {1261return function() {log.push("ch " + i);};1262}(i));1263}1264cm.replaceRange("x", Pos(0, 1));1265cm.replaceRange("xy", Pos(1, 1), Pos(2));1266cm.replaceRange("foo\nbar", Pos(0, 1));1267cm.replaceRange("", Pos(0, 0), Pos(cm.lineCount()));1268eq(log.length, want.length, "same length");1269for (var i = 0; i < log.length; ++i)1270eq(log[i], want[i]);1271});12721273testCM("scrollEntirelyToRight", function(cm) {1274if (phantom) return;1275addDoc(cm, 500, 2);1276cm.setCursor(Pos(0, 500));1277var wrap = cm.getWrapperElement(), cur = byClassName(wrap, "CodeMirror-cursor")[0];1278is(wrap.getBoundingClientRect().right > cur.getBoundingClientRect().left);1279});12801281testCM("lineWidgets", function(cm) {1282addDoc(cm, 500, 3);1283var last = cm.charCoords(Pos(2, 0));1284var node = document.createElement("div");1285node.innerHTML = "hi";1286var widget = cm.addLineWidget(1, node);1287is(last.top < cm.charCoords(Pos(2, 0)).top, "took up space");1288cm.setCursor(Pos(1, 1));1289cm.execCommand("goLineDown");1290eqPos(cm.getCursor(), Pos(2, 1));1291cm.execCommand("goLineUp");1292eqPos(cm.getCursor(), Pos(1, 1));1293});12941295testCM("lineWidgetFocus", function(cm) {1296var place = document.getElementById("testground");1297place.className = "offscreen";1298try {1299addDoc(cm, 500, 10);1300var node = document.createElement("input");1301var widget = cm.addLineWidget(1, node);1302node.focus();1303eq(document.activeElement, node);1304cm.replaceRange("new stuff", Pos(1, 0));1305eq(document.activeElement, node);1306} finally {1307place.className = "";1308}1309});13101311testCM("getLineNumber", function(cm) {1312addDoc(cm, 2, 20);1313var h1 = cm.getLineHandle(1);1314eq(cm.getLineNumber(h1), 1);1315cm.replaceRange("hi\nbye\n", Pos(0, 0));1316eq(cm.getLineNumber(h1), 3);1317cm.setValue("");1318eq(cm.getLineNumber(h1), null);1319});13201321testCM("jumpTheGap", function(cm) {1322var longLine = "abcdef ghiklmnop qrstuvw xyz ";1323longLine += longLine; longLine += longLine; longLine += longLine;1324cm.setLine(2, longLine);1325cm.setSize("200px", null);1326cm.getWrapperElement().style.lineHeight = 2;1327cm.refresh();1328cm.setCursor(Pos(0, 1));1329cm.execCommand("goLineDown");1330eqPos(cm.getCursor(), Pos(1, 1));1331cm.execCommand("goLineDown");1332eqPos(cm.getCursor(), Pos(2, 1));1333cm.execCommand("goLineDown");1334eq(cm.getCursor().line, 2);1335is(cm.getCursor().ch > 1);1336cm.execCommand("goLineUp");1337eqPos(cm.getCursor(), Pos(2, 1));1338cm.execCommand("goLineUp");1339eqPos(cm.getCursor(), Pos(1, 1));1340var node = document.createElement("div");1341node.innerHTML = "hi"; node.style.height = "30px";1342cm.addLineWidget(0, node);1343cm.addLineWidget(1, node.cloneNode(true), {above: true});1344cm.setCursor(Pos(0, 2));1345cm.execCommand("goLineDown");1346eqPos(cm.getCursor(), Pos(1, 2));1347cm.execCommand("goLineUp");1348eqPos(cm.getCursor(), Pos(0, 2));1349}, {lineWrapping: true, value: "abc\ndef\nghi\njkl\n"});13501351testCM("addLineClass", function(cm) {1352function cls(line, text, bg, wrap) {1353var i = cm.lineInfo(line);1354eq(i.textClass, text);1355eq(i.bgClass, bg);1356eq(i.wrapClass, wrap);1357}1358cm.addLineClass(0, "text", "foo");1359cm.addLineClass(0, "text", "bar");1360cm.addLineClass(1, "background", "baz");1361cm.addLineClass(1, "wrap", "foo");1362cls(0, "foo bar", null, null);1363cls(1, null, "baz", "foo");1364var lines = cm.display.lineDiv;1365eq(byClassName(lines, "foo").length, 2);1366eq(byClassName(lines, "bar").length, 1);1367eq(byClassName(lines, "baz").length, 1);1368cm.removeLineClass(0, "text", "foo");1369cls(0, "bar", null, null);1370cm.removeLineClass(0, "text", "foo");1371cls(0, "bar", null, null);1372cm.removeLineClass(0, "text", "bar");1373cls(0, null, null, null);1374cm.addLineClass(1, "wrap", "quux");1375cls(1, null, "baz", "foo quux");1376cm.removeLineClass(1, "wrap");1377cls(1, null, "baz", null);1378}, {value: "hohoho\n"});13791380testCM("atomicMarker", function(cm) {1381addDoc(cm, 10, 10);1382function atom(ll, cl, lr, cr, li, ri) {1383return cm.markText(Pos(ll, cl), Pos(lr, cr),1384{atomic: true, inclusiveLeft: li, inclusiveRight: ri});1385}1386var m = atom(0, 1, 0, 5);1387cm.setCursor(Pos(0, 1));1388cm.execCommand("goCharRight");1389eqPos(cm.getCursor(), Pos(0, 5));1390cm.execCommand("goCharLeft");1391eqPos(cm.getCursor(), Pos(0, 1));1392m.clear();1393m = atom(0, 0, 0, 5, true);1394eqPos(cm.getCursor(), Pos(0, 5), "pushed out");1395cm.execCommand("goCharLeft");1396eqPos(cm.getCursor(), Pos(0, 5));1397m.clear();1398m = atom(8, 4, 9, 10, false, true);1399cm.setCursor(Pos(9, 8));1400eqPos(cm.getCursor(), Pos(8, 4), "set");1401cm.execCommand("goCharRight");1402eqPos(cm.getCursor(), Pos(8, 4), "char right");1403cm.execCommand("goLineDown");1404eqPos(cm.getCursor(), Pos(8, 4), "line down");1405cm.execCommand("goCharLeft");1406eqPos(cm.getCursor(), Pos(8, 3));1407m.clear();1408m = atom(1, 1, 3, 8);1409cm.setCursor(Pos(0, 0));1410cm.setCursor(Pos(2, 0));1411eqPos(cm.getCursor(), Pos(3, 8));1412cm.execCommand("goCharLeft");1413eqPos(cm.getCursor(), Pos(1, 1));1414cm.execCommand("goCharRight");1415eqPos(cm.getCursor(), Pos(3, 8));1416cm.execCommand("goLineUp");1417eqPos(cm.getCursor(), Pos(1, 1));1418cm.execCommand("goLineDown");1419eqPos(cm.getCursor(), Pos(3, 8));1420cm.execCommand("delCharBefore");1421eq(cm.getValue().length, 80, "del chunk");1422m = atom(3, 0, 5, 5);1423cm.setCursor(Pos(3, 0));1424cm.execCommand("delWordAfter");1425eq(cm.getValue().length, 53, "del chunk");1426});14271428testCM("readOnlyMarker", function(cm) {1429function mark(ll, cl, lr, cr, at) {1430return cm.markText(Pos(ll, cl), Pos(lr, cr),1431{readOnly: true, atomic: at});1432}1433var m = mark(0, 1, 0, 4);1434cm.setCursor(Pos(0, 2));1435cm.replaceSelection("hi", "end");1436eqPos(cm.getCursor(), Pos(0, 2));1437eq(cm.getLine(0), "abcde");1438cm.execCommand("selectAll");1439cm.replaceSelection("oops");1440eq(cm.getValue(), "oopsbcd");1441cm.undo();1442eqPos(m.find().from, Pos(0, 1));1443eqPos(m.find().to, Pos(0, 4));1444m.clear();1445cm.setCursor(Pos(0, 2));1446cm.replaceSelection("hi");1447eq(cm.getLine(0), "abhicde");1448eqPos(cm.getCursor(), Pos(0, 4));1449m = mark(0, 2, 2, 2, true);1450cm.setSelection(Pos(1, 1), Pos(2, 4));1451cm.replaceSelection("t", "end");1452eqPos(cm.getCursor(), Pos(2, 3));1453eq(cm.getLine(2), "klto");1454cm.execCommand("goCharLeft");1455cm.execCommand("goCharLeft");1456eqPos(cm.getCursor(), Pos(0, 2));1457cm.setSelection(Pos(0, 1), Pos(0, 3));1458cm.replaceSelection("xx");1459eqPos(cm.getCursor(), Pos(0, 3));1460eq(cm.getLine(0), "axxhicde");1461}, {value: "abcde\nfghij\nklmno\n"});14621463testCM("dirtyBit", function(cm) {1464eq(cm.isClean(), true);1465cm.replaceSelection("boo");1466eq(cm.isClean(), false);1467cm.undo();1468eq(cm.isClean(), true);1469cm.replaceSelection("boo");1470cm.replaceSelection("baz");1471cm.undo();1472eq(cm.isClean(), false);1473cm.markClean();1474eq(cm.isClean(), true);1475cm.undo();1476eq(cm.isClean(), false);1477cm.redo();1478eq(cm.isClean(), true);1479});14801481testCM("changeGeneration", function(cm) {1482cm.replaceSelection("x", null, "+insert");1483var softGen = cm.changeGeneration();1484cm.replaceSelection("x", null, "+insert");1485cm.undo();1486eq(cm.getValue(), "");1487is(!cm.isClean(softGen));1488cm.replaceSelection("x", null, "+insert");1489var hardGen = cm.changeGeneration(true);1490cm.replaceSelection("x", null, "+insert");1491cm.undo();1492eq(cm.getValue(), "x");1493is(cm.isClean(hardGen));1494});14951496testCM("addKeyMap", function(cm) {1497function sendKey(code) {1498cm.triggerOnKeyDown({type: "keydown", keyCode: code,1499preventDefault: function(){}, stopPropagation: function(){}});1500}15011502sendKey(39);1503eqPos(cm.getCursor(), Pos(0, 1));1504var test = 0;1505var map1 = {Right: function() { ++test; }}, map2 = {Right: function() { test += 10; }}1506cm.addKeyMap(map1);1507sendKey(39);1508eqPos(cm.getCursor(), Pos(0, 1));1509eq(test, 1);1510cm.addKeyMap(map2, true);1511sendKey(39);1512eq(test, 2);1513cm.removeKeyMap(map1);1514sendKey(39);1515eq(test, 12);1516cm.removeKeyMap(map2);1517sendKey(39);1518eq(test, 12);1519eqPos(cm.getCursor(), Pos(0, 2));1520cm.addKeyMap({Right: function() { test = 55; }, name: "mymap"});1521sendKey(39);1522eq(test, 55);1523cm.removeKeyMap("mymap");1524sendKey(39);1525eqPos(cm.getCursor(), Pos(0, 3));1526}, {value: "abc"});15271528testCM("findPosH", function(cm) {1529forEach([{from: Pos(0, 0), to: Pos(0, 1), by: 1},1530{from: Pos(0, 0), to: Pos(0, 0), by: -1, hitSide: true},1531{from: Pos(0, 0), to: Pos(0, 4), by: 1, unit: "word"},1532{from: Pos(0, 0), to: Pos(0, 8), by: 2, unit: "word"},1533{from: Pos(0, 0), to: Pos(2, 0), by: 20, unit: "word", hitSide: true},1534{from: Pos(0, 7), to: Pos(0, 5), by: -1, unit: "word"},1535{from: Pos(0, 4), to: Pos(0, 8), by: 1, unit: "word"},1536{from: Pos(1, 0), to: Pos(1, 18), by: 3, unit: "word"},1537{from: Pos(1, 22), to: Pos(1, 5), by: -3, unit: "word"},1538{from: Pos(1, 15), to: Pos(1, 10), by: -5},1539{from: Pos(1, 15), to: Pos(1, 10), by: -5, unit: "column"},1540{from: Pos(1, 15), to: Pos(1, 0), by: -50, unit: "column", hitSide: true},1541{from: Pos(1, 15), to: Pos(1, 24), by: 50, unit: "column", hitSide: true},1542{from: Pos(1, 15), to: Pos(2, 0), by: 50, hitSide: true}], function(t) {1543var r = cm.findPosH(t.from, t.by, t.unit || "char");1544eqPos(r, t.to);1545eq(!!r.hitSide, !!t.hitSide);1546});1547}, {value: "line one\nline two.something.other\n"});15481549testCM("beforeChange", function(cm) {1550cm.on("beforeChange", function(cm, change) {1551var text = [];1552for (var i = 0; i < change.text.length; ++i)1553text.push(change.text[i].replace(/\s/g, "_"));1554change.update(null, null, text);1555});1556cm.setValue("hello, i am a\nnew document\n");1557eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");1558CodeMirror.on(cm.getDoc(), "beforeChange", function(doc, change) {1559if (change.from.line == 0) change.cancel();1560});1561cm.setValue("oops"); // Canceled1562eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");1563cm.replaceRange("hey hey hey", Pos(1, 0), Pos(2, 0));1564eq(cm.getValue(), "hello,_i_am_a\nhey_hey_hey");1565}, {value: "abcdefghijk"});15661567testCM("beforeChangeUndo", function(cm) {1568cm.setLine(0, "hi");1569cm.setLine(0, "bye");1570eq(cm.historySize().undo, 2);1571cm.on("beforeChange", function(cm, change) {1572is(!change.update);1573change.cancel();1574});1575cm.undo();1576eq(cm.historySize().undo, 0);1577eq(cm.getValue(), "bye\ntwo");1578}, {value: "one\ntwo"});15791580testCM("beforeSelectionChange", function(cm) {1581function notAtEnd(cm, pos) {1582var len = cm.getLine(pos.line).length;1583if (!len || pos.ch == len) return Pos(pos.line, pos.ch - 1);1584return pos;1585}1586cm.on("beforeSelectionChange", function(cm, sel) {1587sel.head = notAtEnd(cm, sel.head);1588sel.anchor = notAtEnd(cm, sel.anchor);1589});15901591addDoc(cm, 10, 10);1592cm.execCommand("goLineEnd");1593eqPos(cm.getCursor(), Pos(0, 9));1594cm.execCommand("selectAll");1595eqPos(cm.getCursor("start"), Pos(0, 0));1596eqPos(cm.getCursor("end"), Pos(9, 9));1597});15981599testCM("change_removedText", function(cm) {1600cm.setValue("abc\ndef");16011602var removedText;1603cm.on("change", function(cm, change) {1604removedText = [change.removed, change.next && change.next.removed];1605});16061607cm.operation(function() {1608cm.replaceRange("xyz", Pos(0, 0), Pos(1,1));1609cm.replaceRange("123", Pos(0,0));1610});16111612eq(removedText[0].join("\n"), "abc\nd");1613eq(removedText[1].join("\n"), "");16141615cm.undo();1616eq(removedText[0].join("\n"), "123");1617eq(removedText[1].join("\n"), "xyz");16181619cm.redo();1620eq(removedText[0].join("\n"), "abc\nd");1621eq(removedText[1].join("\n"), "");1622});16231624testCM("lineStyleFromMode", function(cm) {1625CodeMirror.defineMode("test_mode", function() {1626return {token: function(stream) {1627if (stream.match(/^\[[^\]]*\]/)) return "line-brackets";1628if (stream.match(/^\([^\]]*\)/)) return "line-background-parens";1629stream.match(/^\s+|^\S+/);1630}};1631});1632cm.setOption("mode", "test_mode");1633var bracketElts = byClassName(cm.getWrapperElement(), "brackets");1634eq(bracketElts.length, 1);1635eq(bracketElts[0].nodeName, "PRE");1636is(!/brackets.*brackets/.test(bracketElts[0].className));1637var parenElts = byClassName(cm.getWrapperElement(), "parens");1638eq(parenElts.length, 1);1639eq(parenElts[0].nodeName, "DIV");1640is(!/parens.*parens/.test(parenElts[0].className));1641}, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: nothing"});16421643CodeMirror.registerHelper("xxx", "a", "A");1644CodeMirror.registerHelper("xxx", "b", "B");1645CodeMirror.defineMode("yyy", function() {1646return {1647token: function(stream) { stream.skipToEnd(); },1648xxx: ["a", "b", "q"]1649};1650});1651CodeMirror.registerGlobalHelper("xxx", "c", function(m) { return m.enableC; }, "C");16521653testCM("helpers", function(cm) {1654cm.setOption("mode", "yyy");1655eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "A/B");1656cm.setOption("mode", {name: "yyy", modeProps: {xxx: "b", enableC: true}});1657eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "B/C");1658cm.setOption("mode", "javascript");1659eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "");1660});166116621663