vim_test.js 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060
  1. var code = '' +
  2. ' wOrd1 (#%\n' +
  3. ' word3] \n' +
  4. 'aopop pop 0 1 2 3 4\n' +
  5. ' (a) [b] {c} \n' +
  6. 'int getchar(void) {\n' +
  7. ' static char buf[BUFSIZ];\n' +
  8. ' static char *bufp = buf;\n' +
  9. ' if (n == 0) { /* buffer is empty */\n' +
  10. ' n = read(0, buf, sizeof buf);\n' +
  11. ' bufp = buf;\n' +
  12. ' }\n' +
  13. '\n' +
  14. ' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' +
  15. ' \n' +
  16. '}\n';
  17. var lines = (function() {
  18. lineText = code.split('\n');
  19. var ret = [];
  20. for (var i = 0; i < lineText.length; i++) {
  21. ret[i] = {
  22. line: i,
  23. length: lineText[i].length,
  24. lineText: lineText[i],
  25. textStart: /^\s*/.exec(lineText[i])[0].length
  26. };
  27. }
  28. return ret;
  29. })();
  30. var endOfDocument = makeCursor(lines.length - 1,
  31. lines[lines.length - 1].length);
  32. var wordLine = lines[0];
  33. var bigWordLine = lines[1];
  34. var charLine = lines[2];
  35. var bracesLine = lines[3];
  36. var seekBraceLine = lines[4];
  37. var word1 = {
  38. start: { line: wordLine.line, ch: 1 },
  39. end: { line: wordLine.line, ch: 5 }
  40. };
  41. var word2 = {
  42. start: { line: wordLine.line, ch: word1.end.ch + 2 },
  43. end: { line: wordLine.line, ch: word1.end.ch + 4 }
  44. };
  45. var word3 = {
  46. start: { line: bigWordLine.line, ch: 1 },
  47. end: { line: bigWordLine.line, ch: 5 }
  48. };
  49. var bigWord1 = word1;
  50. var bigWord2 = word2;
  51. var bigWord3 = {
  52. start: { line: bigWordLine.line, ch: 1 },
  53. end: { line: bigWordLine.line, ch: 7 }
  54. };
  55. var bigWord4 = {
  56. start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 },
  57. end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 }
  58. };
  59. var oChars = [ { line: charLine.line, ch: 1 },
  60. { line: charLine.line, ch: 3 },
  61. { line: charLine.line, ch: 7 } ];
  62. var pChars = [ { line: charLine.line, ch: 2 },
  63. { line: charLine.line, ch: 4 },
  64. { line: charLine.line, ch: 6 },
  65. { line: charLine.line, ch: 8 } ];
  66. var numChars = [ { line: charLine.line, ch: 10 },
  67. { line: charLine.line, ch: 12 },
  68. { line: charLine.line, ch: 14 },
  69. { line: charLine.line, ch: 16 },
  70. { line: charLine.line, ch: 18 }];
  71. var parens1 = {
  72. start: { line: bracesLine.line, ch: 1 },
  73. end: { line: bracesLine.line, ch: 3 }
  74. };
  75. var squares1 = {
  76. start: { line: bracesLine.line, ch: 5 },
  77. end: { line: bracesLine.line, ch: 7 }
  78. };
  79. var curlys1 = {
  80. start: { line: bracesLine.line, ch: 9 },
  81. end: { line: bracesLine.line, ch: 11 }
  82. };
  83. var seekOutside = {
  84. start: { line: seekBraceLine.line, ch: 1 },
  85. end: { line: seekBraceLine.line, ch: 16 }
  86. };
  87. var seekInside = {
  88. start: { line: seekBraceLine.line, ch: 14 },
  89. end: { line: seekBraceLine.line, ch: 11 }
  90. };
  91. function copyCursor(cur) {
  92. return { ch: cur.ch, line: cur.line };
  93. }
  94. function testVim(name, run, opts, expectedFail) {
  95. var vimOpts = {
  96. lineNumbers: true,
  97. keyMap: 'vim',
  98. showCursorWhenSelecting: true,
  99. value: code
  100. };
  101. for (var prop in opts) {
  102. if (opts.hasOwnProperty(prop)) {
  103. vimOpts[prop] = opts[prop];
  104. }
  105. }
  106. return test('vim_' + name, function() {
  107. var place = document.getElementById("testground");
  108. var cm = CodeMirror(place, vimOpts);
  109. CodeMirror.Vim.maybeInitState(cm);
  110. var vim = cm.vimState;
  111. function doKeysFn(cm) {
  112. return function(args) {
  113. if (args instanceof Array) {
  114. arguments = args;
  115. }
  116. for (var i = 0; i < arguments.length; i++) {
  117. CodeMirror.Vim.handleKey(cm, arguments[i]);
  118. }
  119. }
  120. }
  121. function doExFn(cm) {
  122. return function(command) {
  123. cm.openDialog = helpers.fakeOpenDialog(command);
  124. helpers.doKeys(':');
  125. }
  126. }
  127. function assertCursorAtFn(cm) {
  128. return function(line, ch) {
  129. var pos;
  130. if (ch == null && typeof line.line == 'number') {
  131. pos = line;
  132. } else {
  133. pos = makeCursor(line, ch);
  134. }
  135. eqPos(pos, cm.getCursor());
  136. }
  137. }
  138. function fakeOpenDialog(result) {
  139. return function(text, callback) {
  140. return callback(result);
  141. }
  142. }
  143. var helpers = {
  144. doKeys: doKeysFn(cm),
  145. doEx: doExFn(cm),
  146. assertCursorAt: assertCursorAtFn(cm),
  147. fakeOpenDialog: fakeOpenDialog,
  148. getRegisterController: function() {
  149. return CodeMirror.Vim.getRegisterController();
  150. }
  151. }
  152. CodeMirror.Vim.clearVimGlobalState_();
  153. var successful = false;
  154. try {
  155. run(cm, vim, helpers);
  156. successful = true;
  157. } finally {
  158. if ((debug && !successful) || verbose) {
  159. place.style.visibility = "visible";
  160. } else {
  161. place.removeChild(cm.getWrapperElement());
  162. }
  163. }
  164. }, expectedFail);
  165. };
  166. testVim('qq@q', function(cm, vim, helpers) {
  167. cm.setCursor(0, 0);
  168. helpers.doKeys('q', 'q', 'l', 'l', 'q');
  169. helpers.assertCursorAt(0,2);
  170. helpers.doKeys('@', 'q');
  171. helpers.assertCursorAt(0,4);
  172. }, { value: ' '});
  173. testVim('@@', function(cm, vim, helpers) {
  174. cm.setCursor(0, 0);
  175. helpers.doKeys('q', 'q', 'l', 'l', 'q');
  176. helpers.assertCursorAt(0,2);
  177. helpers.doKeys('@', 'q');
  178. helpers.assertCursorAt(0,4);
  179. helpers.doKeys('@', '@');
  180. helpers.assertCursorAt(0,6);
  181. }, { value: ' '});
  182. var jumplistScene = ''+
  183. 'word\n'+
  184. '(word)\n'+
  185. '{word\n'+
  186. 'word.\n'+
  187. '\n'+
  188. 'word search\n'+
  189. '}word\n'+
  190. 'word\n'+
  191. 'word\n';
  192. function testJumplist(name, keys, endPos, startPos, dialog) {
  193. endPos = makeCursor(endPos[0], endPos[1]);
  194. startPos = makeCursor(startPos[0], startPos[1]);
  195. testVim(name, function(cm, vim, helpers) {
  196. CodeMirror.Vim.clearVimGlobalState_();
  197. if(dialog)cm.openDialog = helpers.fakeOpenDialog('word');
  198. cm.setCursor(startPos);
  199. helpers.doKeys.apply(null, keys);
  200. helpers.assertCursorAt(endPos);
  201. }, {value: jumplistScene});
  202. };
  203. testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]);
  204. testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]);
  205. testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]);
  206. testJumplist('jumplist_[[', ['[', '[', '<C-o>'], [5,2], [5,2]);
  207. testJumplist('jumplist_]]', [']', ']', '<C-o>'], [2,2], [2,2]);
  208. testJumplist('jumplist_G', ['G', '<C-o>'], [5,2], [5,2]);
  209. testJumplist('jumplist_gg', ['g', 'g', '<C-o>'], [5,2], [5,2]);
  210. testJumplist('jumplist_%', ['%', '<C-o>'], [1,5], [1,5]);
  211. testJumplist('jumplist_{', ['{', '<C-o>'], [1,5], [1,5]);
  212. testJumplist('jumplist_}', ['}', '<C-o>'], [1,5], [1,5]);
  213. testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', '<C-i>'], [1,5], [1,5]);
  214. testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', '<C-i>'], [1,5], [1,5]);
  215. testJumplist('jumplist_*_cachedCursor', ['*', '<C-o>'], [1,3], [1,3]);
  216. testJumplist('jumplist_#_cachedCursor', ['#', '<C-o>'], [1,3], [1,3]);
  217. testJumplist('jumplist_n', ['#', 'n', '<C-o>'], [1,1], [2,3]);
  218. testJumplist('jumplist_N', ['#', 'N', '<C-o>'], [1,1], [2,3]);
  219. testJumplist('jumplist_repeat_<c-o>', ['*', '*', '*', '3', '<C-o>'], [2,3], [2,3]);
  220. testJumplist('jumplist_repeat_<c-i>', ['*', '*', '*', '3', '<C-o>', '2', '<C-i>'], [5,0], [2,3]);
  221. testJumplist('jumplist_repeated_motion', ['3', '*', '<C-o>'], [2,3], [2,3]);
  222. testJumplist('jumplist_/', ['/', '<C-o>'], [2,3], [2,3], 'dialog');
  223. testJumplist('jumplist_?', ['?', '<C-o>'], [2,3], [2,3], 'dialog');
  224. testJumplist('jumplist_skip_delted_mark<c-o>',
  225. ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-o>', '<C-o>'],
  226. [0,2], [0,2]);
  227. testJumplist('jumplist_skip_delted_mark<c-i>',
  228. ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-i>', '<C-i>'],
  229. [1,0], [0,2]);
  230. /**
  231. * @param name Name of the test
  232. * @param keys An array of keys or a string with a single key to simulate.
  233. * @param endPos The expected end position of the cursor.
  234. * @param startPos The position the cursor should start at, defaults to 0, 0.
  235. */
  236. function testMotion(name, keys, endPos, startPos) {
  237. testVim(name, function(cm, vim, helpers) {
  238. if (!startPos) {
  239. startPos = { line: 0, ch: 0 };
  240. }
  241. cm.setCursor(startPos);
  242. helpers.doKeys(keys);
  243. helpers.assertCursorAt(endPos);
  244. });
  245. };
  246. function makeCursor(line, ch) {
  247. return { line: line, ch: ch };
  248. };
  249. function offsetCursor(cur, offsetLine, offsetCh) {
  250. return { line: cur.line + offsetLine, ch: cur.ch + offsetCh };
  251. };
  252. // Motion tests
  253. testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4));
  254. testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4));
  255. testMotion('h', 'h', makeCursor(0, 0), word1.start);
  256. testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end);
  257. testMotion('l', 'l', makeCursor(0, 1));
  258. testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2));
  259. testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end);
  260. testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end);
  261. testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end);
  262. testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4));
  263. testMotion('w', 'w', word1.start);
  264. testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2));
  265. testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51));
  266. testMotion('w_repeat', ['2', 'w'], word2.start);
  267. testMotion('w_wrap', ['w'], word3.start, word2.start);
  268. testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument);
  269. testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0));
  270. testMotion('W', 'W', bigWord1.start);
  271. testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start);
  272. testMotion('e', 'e', word1.end);
  273. testMotion('e_repeat', ['2', 'e'], word2.end);
  274. testMotion('e_wrap', 'e', word3.end, word2.end);
  275. testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument);
  276. testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0));
  277. testMotion('b', 'b', word3.start, word3.end);
  278. testMotion('b_repeat', ['2', 'b'], word2.start, word3.end);
  279. testMotion('b_wrap', 'b', word2.start, word3.start);
  280. testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0));
  281. testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument);
  282. testMotion('ge', ['g', 'e'], word2.end, word3.end);
  283. testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start);
  284. testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start);
  285. testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0),
  286. makeCursor(0, 0));
  287. testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument);
  288. testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart),
  289. makeCursor(3, 1));
  290. testMotion('gg_repeat', ['3', 'g', 'g'],
  291. makeCursor(lines[2].line, lines[2].textStart));
  292. testMotion('G', 'G',
  293. makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart),
  294. makeCursor(3, 1));
  295. testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line,
  296. lines[2].textStart));
  297. // TODO: Make the test code long enough to test Ctrl-F and Ctrl-B.
  298. testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8));
  299. testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8));
  300. testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8));
  301. testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4));
  302. testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8));
  303. testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1));
  304. testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1),
  305. makeCursor(0, 3));
  306. testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0));
  307. testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]);
  308. testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0));
  309. testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1),
  310. makeCursor(charLine.line, 0));
  311. testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1),
  312. pChars[0]);
  313. testMotion('F', ['F', 'p'], pChars[0], pChars[1]);
  314. testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]);
  315. testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]);
  316. testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]);
  317. testMotion('%_parens', ['%'], parens1.end, parens1.start);
  318. testMotion('%_squares', ['%'], squares1.end, squares1.start);
  319. testMotion('%_braces', ['%'], curlys1.end, curlys1.start);
  320. testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start);
  321. testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start);
  322. testVim('%_seek_skip', function(cm, vim, helpers) {
  323. cm.setCursor(0,0);
  324. helpers.doKeys(['%']);
  325. helpers.assertCursorAt(0,9);
  326. }, {value:'01234"("()'});
  327. testVim('%_skip_string', function(cm, vim, helpers) {
  328. cm.setCursor(0,0);
  329. helpers.doKeys(['%']);
  330. helpers.assertCursorAt(0,4);
  331. cm.setCursor(0,2);
  332. helpers.doKeys(['%']);
  333. helpers.assertCursorAt(0,0);
  334. }, {value:'(")")'});
  335. (')')
  336. testVim('%_skip_comment', function(cm, vim, helpers) {
  337. cm.setCursor(0,0);
  338. helpers.doKeys(['%']);
  339. helpers.assertCursorAt(0,6);
  340. cm.setCursor(0,3);
  341. helpers.doKeys(['%']);
  342. helpers.assertCursorAt(0,0);
  343. }, {value:'(/*)*/)'});
  344. // Make sure that moving down after going to the end of a line always leaves you
  345. // at the end of a line, but preserves the offset in other cases
  346. testVim('Changing lines after Eol operation', function(cm, vim, helpers) {
  347. cm.setCursor(0,0);
  348. helpers.doKeys(['$']);
  349. helpers.doKeys(['j']);
  350. // After moving to Eol and then down, we should be at Eol of line 2
  351. helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 });
  352. helpers.doKeys(['j']);
  353. // After moving down, we should be at Eol of line 3
  354. helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 });
  355. helpers.doKeys(['h']);
  356. helpers.doKeys(['j']);
  357. // After moving back one space and then down, since line 4 is shorter than line 2, we should
  358. // be at Eol of line 2 - 1
  359. helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 });
  360. helpers.doKeys(['j']);
  361. helpers.doKeys(['j']);
  362. // After moving down again, since line 3 has enough characters, we should be back to the
  363. // same place we were at on line 1
  364. helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 });
  365. });
  366. //making sure gj and gk recover from clipping
  367. testVim('gj_gk_clipping', function(cm,vim,helpers){
  368. cm.setCursor(0, 1);
  369. helpers.doKeys('g','j','g','j');
  370. helpers.assertCursorAt(2, 1);
  371. helpers.doKeys('g','k','g','k');
  372. helpers.assertCursorAt(0, 1);
  373. },{value: 'line 1\n\nline 2'});
  374. //testing a mix of j/k and gj/gk
  375. testVim('j_k_and_gj_gk', function(cm,vim,helpers){
  376. cm.setSize(120);
  377. cm.setCursor(0, 0);
  378. //go to the last character on the first line
  379. helpers.doKeys('$');
  380. //move up/down on the column within the wrapped line
  381. //side-effect: cursor is not locked to eol anymore
  382. helpers.doKeys('g','k');
  383. var cur=cm.getCursor();
  384. eq(cur.line,0);
  385. is((cur.ch<176),'gk didn\'t move cursor back (1)');
  386. helpers.doKeys('g','j');
  387. helpers.assertCursorAt(0, 176);
  388. //should move to character 177 on line 2 (j/k preserve character index within line)
  389. helpers.doKeys('j');
  390. //due to different line wrapping, the cursor can be on a different screen-x now
  391. //gj and gk preserve screen-x on movement, much like moveV
  392. helpers.doKeys('3','g','k');
  393. cur=cm.getCursor();
  394. eq(cur.line,1);
  395. is((cur.ch<176),'gk didn\'t move cursor back (2)');
  396. helpers.doKeys('g','j','2','g','j');
  397. //should return to the same character-index
  398. helpers.doKeys('k');
  399. helpers.assertCursorAt(0, 176);
  400. },{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'});
  401. testVim('gj_gk', function(cm, vim, helpers) {
  402. if (phantom) return;
  403. cm.setSize(120);
  404. // Test top of document edge case.
  405. cm.setCursor(0, 4);
  406. helpers.doKeys('g', 'j');
  407. helpers.doKeys('10', 'g', 'k');
  408. helpers.assertCursorAt(0, 4);
  409. // Test moving down preserves column position.
  410. helpers.doKeys('g', 'j');
  411. var pos1 = cm.getCursor();
  412. var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4};
  413. helpers.doKeys('g', 'j');
  414. helpers.assertCursorAt(expectedPos2);
  415. // Move to the last character
  416. cm.setCursor(0, 0);
  417. // Move left to reset HSPos
  418. helpers.doKeys('h');
  419. // Test bottom of document edge case.
  420. helpers.doKeys('100', 'g', 'j');
  421. var endingPos = cm.getCursor();
  422. is(endingPos != 0, 'gj should not be on wrapped line 0');
  423. var topLeftCharCoords = cm.charCoords(makeCursor(0, 0));
  424. var endingCharCoords = cm.charCoords(endingPos);
  425. is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0');
  426. },{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' });
  427. testVim('}', function(cm, vim, helpers) {
  428. cm.setCursor(0, 0);
  429. helpers.doKeys('}');
  430. helpers.assertCursorAt(1, 0);
  431. cm.setCursor(0, 0);
  432. helpers.doKeys('2', '}');
  433. helpers.assertCursorAt(4, 0);
  434. cm.setCursor(0, 0);
  435. helpers.doKeys('6', '}');
  436. helpers.assertCursorAt(5, 0);
  437. }, { value: 'a\n\nb\nc\n\nd' });
  438. testVim('{', function(cm, vim, helpers) {
  439. cm.setCursor(5, 0);
  440. helpers.doKeys('{');
  441. helpers.assertCursorAt(4, 0);
  442. cm.setCursor(5, 0);
  443. helpers.doKeys('2', '{');
  444. helpers.assertCursorAt(1, 0);
  445. cm.setCursor(5, 0);
  446. helpers.doKeys('6', '{');
  447. helpers.assertCursorAt(0, 0);
  448. }, { value: 'a\n\nb\nc\n\nd' });
  449. // Operator tests
  450. testVim('dl', function(cm, vim, helpers) {
  451. var curStart = makeCursor(0, 0);
  452. cm.setCursor(curStart);
  453. helpers.doKeys('d', 'l');
  454. eq('word1 ', cm.getValue());
  455. var register = helpers.getRegisterController().getRegister();
  456. eq(' ', register.text);
  457. is(!register.linewise);
  458. eqPos(curStart, cm.getCursor());
  459. }, { value: ' word1 ' });
  460. testVim('dl_eol', function(cm, vim, helpers) {
  461. // TODO: This test is incorrect. The cursor should end up at (0, 5).
  462. var curStart = makeCursor(0, 6);
  463. cm.setCursor(curStart);
  464. helpers.doKeys('d', 'l');
  465. eq(' word1', cm.getValue());
  466. var register = helpers.getRegisterController().getRegister();
  467. eq(' ', register.text);
  468. is(!register.linewise);
  469. helpers.assertCursorAt(0, 6);
  470. }, { value: ' word1 ' });
  471. testVim('dl_repeat', function(cm, vim, helpers) {
  472. var curStart = makeCursor(0, 0);
  473. cm.setCursor(curStart);
  474. helpers.doKeys('2', 'd', 'l');
  475. eq('ord1 ', cm.getValue());
  476. var register = helpers.getRegisterController().getRegister();
  477. eq(' w', register.text);
  478. is(!register.linewise);
  479. eqPos(curStart, cm.getCursor());
  480. }, { value: ' word1 ' });
  481. testVim('dh', function(cm, vim, helpers) {
  482. var curStart = makeCursor(0, 3);
  483. cm.setCursor(curStart);
  484. helpers.doKeys('d', 'h');
  485. eq(' wrd1 ', cm.getValue());
  486. var register = helpers.getRegisterController().getRegister();
  487. eq('o', register.text);
  488. is(!register.linewise);
  489. eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor());
  490. }, { value: ' word1 ' });
  491. testVim('dj', function(cm, vim, helpers) {
  492. var curStart = makeCursor(0, 3);
  493. cm.setCursor(curStart);
  494. helpers.doKeys('d', 'j');
  495. eq(' word3', cm.getValue());
  496. var register = helpers.getRegisterController().getRegister();
  497. eq(' word1\nword2\n', register.text);
  498. is(register.linewise);
  499. helpers.assertCursorAt(0, 1);
  500. }, { value: ' word1\nword2\n word3' });
  501. testVim('dj_end_of_document', function(cm, vim, helpers) {
  502. var curStart = makeCursor(0, 3);
  503. cm.setCursor(curStart);
  504. helpers.doKeys('d', 'j');
  505. eq(' word1 ', cm.getValue());
  506. var register = helpers.getRegisterController().getRegister();
  507. eq('', register.text);
  508. is(!register.linewise);
  509. helpers.assertCursorAt(0, 3);
  510. }, { value: ' word1 ' });
  511. testVim('dk', function(cm, vim, helpers) {
  512. var curStart = makeCursor(1, 3);
  513. cm.setCursor(curStart);
  514. helpers.doKeys('d', 'k');
  515. eq(' word3', cm.getValue());
  516. var register = helpers.getRegisterController().getRegister();
  517. eq(' word1\nword2\n', register.text);
  518. is(register.linewise);
  519. helpers.assertCursorAt(0, 1);
  520. }, { value: ' word1\nword2\n word3' });
  521. testVim('dk_start_of_document', function(cm, vim, helpers) {
  522. var curStart = makeCursor(0, 3);
  523. cm.setCursor(curStart);
  524. helpers.doKeys('d', 'k');
  525. eq(' word1 ', cm.getValue());
  526. var register = helpers.getRegisterController().getRegister();
  527. eq('', register.text);
  528. is(!register.linewise);
  529. helpers.assertCursorAt(0, 3);
  530. }, { value: ' word1 ' });
  531. testVim('dw_space', function(cm, vim, helpers) {
  532. var curStart = makeCursor(0, 0);
  533. cm.setCursor(curStart);
  534. helpers.doKeys('d', 'w');
  535. eq('word1 ', cm.getValue());
  536. var register = helpers.getRegisterController().getRegister();
  537. eq(' ', register.text);
  538. is(!register.linewise);
  539. eqPos(curStart, cm.getCursor());
  540. }, { value: ' word1 ' });
  541. testVim('dw_word', function(cm, vim, helpers) {
  542. var curStart = makeCursor(0, 1);
  543. cm.setCursor(curStart);
  544. helpers.doKeys('d', 'w');
  545. eq(' word2', cm.getValue());
  546. var register = helpers.getRegisterController().getRegister();
  547. eq('word1 ', register.text);
  548. is(!register.linewise);
  549. eqPos(curStart, cm.getCursor());
  550. }, { value: ' word1 word2' });
  551. testVim('dw_only_word', function(cm, vim, helpers) {
  552. // Test that if there is only 1 word left, dw deletes till the end of the
  553. // line.
  554. var curStart = makeCursor(0, 1);
  555. cm.setCursor(curStart);
  556. helpers.doKeys('d', 'w');
  557. eq(' ', cm.getValue());
  558. var register = helpers.getRegisterController().getRegister();
  559. eq('word1 ', register.text);
  560. is(!register.linewise);
  561. eqPos(curStart, cm.getCursor());
  562. }, { value: ' word1 ' });
  563. testVim('dw_eol', function(cm, vim, helpers) {
  564. // Assert that dw does not delete the newline if last word to delete is at end
  565. // of line.
  566. var curStart = makeCursor(0, 1);
  567. cm.setCursor(curStart);
  568. helpers.doKeys('d', 'w');
  569. eq(' \nword2', cm.getValue());
  570. var register = helpers.getRegisterController().getRegister();
  571. eq('word1', register.text);
  572. is(!register.linewise);
  573. eqPos(curStart, cm.getCursor());
  574. }, { value: ' word1\nword2' });
  575. testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {
  576. // Assert that dw does not delete the newline if last word to delete is at end
  577. // of line and it is followed by multiple newlines.
  578. var curStart = makeCursor(0, 1);
  579. cm.setCursor(curStart);
  580. helpers.doKeys('d', 'w');
  581. eq(' \n\nword2', cm.getValue());
  582. var register = helpers.getRegisterController().getRegister();
  583. eq('word1', register.text);
  584. is(!register.linewise);
  585. eqPos(curStart, cm.getCursor());
  586. }, { value: ' word1\n\nword2' });
  587. testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) {
  588. cm.setCursor(0, 0);
  589. helpers.doKeys('d', 'w');
  590. eq(' \nword', cm.getValue());
  591. }, { value: '\n \nword' });
  592. testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) {
  593. cm.setCursor(0, 0);
  594. helpers.doKeys('d', 'w');
  595. eq('word', cm.getValue());
  596. }, { value: '\nword' });
  597. testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) {
  598. cm.setCursor(0, 0);
  599. helpers.doKeys('d', 'w');
  600. eq('\n', cm.getValue());
  601. }, { value: '\n\n' });
  602. testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) {
  603. cm.setCursor(0, 0);
  604. helpers.doKeys('d', 'w');
  605. eq('\n \n', cm.getValue());
  606. }, { value: ' \n \n' });
  607. testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) {
  608. cm.setCursor(0, 0);
  609. helpers.doKeys('d', 'w');
  610. eq('\n\n', cm.getValue());
  611. }, { value: ' \n\n' });
  612. testVim('dw_word_whitespace_word', function(cm, vim, helpers) {
  613. cm.setCursor(0, 0);
  614. helpers.doKeys('d', 'w');
  615. eq('\n \nword2', cm.getValue());
  616. }, { value: 'word1\n \nword2'})
  617. testVim('dw_end_of_document', function(cm, vim, helpers) {
  618. cm.setCursor(1, 2);
  619. helpers.doKeys('d', 'w');
  620. eq('\nab', cm.getValue());
  621. }, { value: '\nabc' });
  622. testVim('dw_repeat', function(cm, vim, helpers) {
  623. // Assert that dw does delete newline if it should go to the next line, and
  624. // that repeat works properly.
  625. var curStart = makeCursor(0, 1);
  626. cm.setCursor(curStart);
  627. helpers.doKeys('d', '2', 'w');
  628. eq(' ', cm.getValue());
  629. var register = helpers.getRegisterController().getRegister();
  630. eq('word1\nword2', register.text);
  631. is(!register.linewise);
  632. eqPos(curStart, cm.getCursor());
  633. }, { value: ' word1\nword2' });
  634. testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) {
  635. cm.setCursor(0, 0);
  636. helpers.doKeys('d', 'e');
  637. eq('\n\n', cm.getValue());
  638. }, { value: 'word\n\n' });
  639. testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) {
  640. cm.setCursor(0, 3);
  641. helpers.doKeys('d', 'e');
  642. eq('wor', cm.getValue());
  643. }, { value: 'word\n\n\n' });
  644. testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) {
  645. cm.setCursor(0, 0);
  646. helpers.doKeys('d', 'e');
  647. eq('', cm.getValue());
  648. }, { value: ' \n\n\n' });
  649. testVim('de_end_of_document', function(cm, vim, helpers) {
  650. cm.setCursor(1, 2);
  651. helpers.doKeys('d', 'e');
  652. eq('\nab', cm.getValue());
  653. }, { value: '\nabc' });
  654. testVim('db_empty_lines', function(cm, vim, helpers) {
  655. cm.setCursor(2, 0);
  656. helpers.doKeys('d', 'b');
  657. eq('\n\n', cm.getValue());
  658. }, { value: '\n\n\n' });
  659. testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) {
  660. cm.setCursor(2, 0);
  661. helpers.doKeys('d', 'b');
  662. eq('\nword', cm.getValue());
  663. }, { value: '\n\nword' });
  664. testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) {
  665. cm.setCursor(2, 3);
  666. helpers.doKeys('d', 'b');
  667. eq('\n\nd', cm.getValue());
  668. }, { value: '\n\nword' });
  669. testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) {
  670. cm.setCursor(2, 0);
  671. helpers.doKeys('d', 'b');
  672. eq('', cm.getValue());
  673. }, { value: '\n \n' });
  674. testVim('db_start_of_document', function(cm, vim, helpers) {
  675. cm.setCursor(0, 0);
  676. helpers.doKeys('d', 'b');
  677. eq('abc\n', cm.getValue());
  678. }, { value: 'abc\n' });
  679. testVim('dge_empty_lines', function(cm, vim, helpers) {
  680. cm.setCursor(1, 0);
  681. helpers.doKeys('d', 'g', 'e');
  682. // Note: In real VIM the result should be '', but it's not quite consistent,
  683. // since 2 newlines are deleted. But in the similar case of word\n\n, only
  684. // 1 newline is deleted. We'll diverge from VIM's behavior since it's much
  685. // easier this way.
  686. eq('\n', cm.getValue());
  687. }, { value: '\n\n' });
  688. testVim('dge_word_and_empty_lines', function(cm, vim, helpers) {
  689. cm.setCursor(1, 0);
  690. helpers.doKeys('d', 'g', 'e');
  691. eq('wor\n', cm.getValue());
  692. }, { value: 'word\n\n'});
  693. testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) {
  694. cm.setCursor(2, 0);
  695. helpers.doKeys('d', 'g', 'e');
  696. eq('', cm.getValue());
  697. }, { value: '\n \n' });
  698. testVim('dge_start_of_document', function(cm, vim, helpers) {
  699. cm.setCursor(0, 0);
  700. helpers.doKeys('d', 'g', 'e');
  701. eq('bc\n', cm.getValue());
  702. }, { value: 'abc\n' });
  703. testVim('d_inclusive', function(cm, vim, helpers) {
  704. // Assert that when inclusive is set, the character the cursor is on gets
  705. // deleted too.
  706. var curStart = makeCursor(0, 1);
  707. cm.setCursor(curStart);
  708. helpers.doKeys('d', 'e');
  709. eq(' ', cm.getValue());
  710. var register = helpers.getRegisterController().getRegister();
  711. eq('word1', register.text);
  712. is(!register.linewise);
  713. eqPos(curStart, cm.getCursor());
  714. }, { value: ' word1 ' });
  715. testVim('d_reverse', function(cm, vim, helpers) {
  716. // Test that deleting in reverse works.
  717. cm.setCursor(1, 0);
  718. helpers.doKeys('d', 'b');
  719. eq(' word2 ', cm.getValue());
  720. var register = helpers.getRegisterController().getRegister();
  721. eq('word1\n', register.text);
  722. is(!register.linewise);
  723. helpers.assertCursorAt(0, 1);
  724. }, { value: ' word1\nword2 ' });
  725. testVim('dd', function(cm, vim, helpers) {
  726. cm.setCursor(0, 3);
  727. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  728. { line: 1, ch: 0 });
  729. var expectedLineCount = cm.lineCount() - 1;
  730. helpers.doKeys('d', 'd');
  731. eq(expectedLineCount, cm.lineCount());
  732. var register = helpers.getRegisterController().getRegister();
  733. eq(expectedBuffer, register.text);
  734. is(register.linewise);
  735. helpers.assertCursorAt(0, lines[1].textStart);
  736. });
  737. testVim('dd_prefix_repeat', function(cm, vim, helpers) {
  738. cm.setCursor(0, 3);
  739. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  740. { line: 2, ch: 0 });
  741. var expectedLineCount = cm.lineCount() - 2;
  742. helpers.doKeys('2', 'd', 'd');
  743. eq(expectedLineCount, cm.lineCount());
  744. var register = helpers.getRegisterController().getRegister();
  745. eq(expectedBuffer, register.text);
  746. is(register.linewise);
  747. helpers.assertCursorAt(0, lines[2].textStart);
  748. });
  749. testVim('dd_motion_repeat', function(cm, vim, helpers) {
  750. cm.setCursor(0, 3);
  751. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  752. { line: 2, ch: 0 });
  753. var expectedLineCount = cm.lineCount() - 2;
  754. helpers.doKeys('d', '2', 'd');
  755. eq(expectedLineCount, cm.lineCount());
  756. var register = helpers.getRegisterController().getRegister();
  757. eq(expectedBuffer, register.text);
  758. is(register.linewise);
  759. helpers.assertCursorAt(0, lines[2].textStart);
  760. });
  761. testVim('dd_multiply_repeat', function(cm, vim, helpers) {
  762. cm.setCursor(0, 3);
  763. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  764. { line: 6, ch: 0 });
  765. var expectedLineCount = cm.lineCount() - 6;
  766. helpers.doKeys('2', 'd', '3', 'd');
  767. eq(expectedLineCount, cm.lineCount());
  768. var register = helpers.getRegisterController().getRegister();
  769. eq(expectedBuffer, register.text);
  770. is(register.linewise);
  771. helpers.assertCursorAt(0, lines[6].textStart);
  772. });
  773. // Yank commands should behave the exact same as d commands, expect that nothing
  774. // gets deleted.
  775. testVim('yw_repeat', function(cm, vim, helpers) {
  776. // Assert that yw does yank newline if it should go to the next line, and
  777. // that repeat works properly.
  778. var curStart = makeCursor(0, 1);
  779. cm.setCursor(curStart);
  780. helpers.doKeys('y', '2', 'w');
  781. eq(' word1\nword2', cm.getValue());
  782. var register = helpers.getRegisterController().getRegister();
  783. eq('word1\nword2', register.text);
  784. is(!register.linewise);
  785. eqPos(curStart, cm.getCursor());
  786. }, { value: ' word1\nword2' });
  787. testVim('yy_multiply_repeat', function(cm, vim, helpers) {
  788. var curStart = makeCursor(0, 3);
  789. cm.setCursor(curStart);
  790. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  791. { line: 6, ch: 0 });
  792. var expectedLineCount = cm.lineCount();
  793. helpers.doKeys('2', 'y', '3', 'y');
  794. eq(expectedLineCount, cm.lineCount());
  795. var register = helpers.getRegisterController().getRegister();
  796. eq(expectedBuffer, register.text);
  797. is(register.linewise);
  798. eqPos(curStart, cm.getCursor());
  799. });
  800. // Change commands behave like d commands except that it also enters insert
  801. // mode. In addition, when the change is linewise, an additional newline is
  802. // inserted so that insert mode starts on that line.
  803. testVim('cw_repeat', function(cm, vim, helpers) {
  804. // Assert that cw does delete newline if it should go to the next line, and
  805. // that repeat works properly.
  806. var curStart = makeCursor(0, 1);
  807. cm.setCursor(curStart);
  808. helpers.doKeys('c', '2', 'w');
  809. eq(' ', cm.getValue());
  810. var register = helpers.getRegisterController().getRegister();
  811. eq('word1\nword2', register.text);
  812. is(!register.linewise);
  813. eqPos(curStart, cm.getCursor());
  814. eq('vim-insert', cm.getOption('keyMap'));
  815. }, { value: ' word1\nword2' });
  816. testVim('cc_multiply_repeat', function(cm, vim, helpers) {
  817. cm.setCursor(0, 3);
  818. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  819. { line: 6, ch: 0 });
  820. var expectedLineCount = cm.lineCount() - 5;
  821. helpers.doKeys('2', 'c', '3', 'c');
  822. eq(expectedLineCount, cm.lineCount());
  823. var register = helpers.getRegisterController().getRegister();
  824. eq(expectedBuffer, register.text);
  825. is(register.linewise);
  826. helpers.assertCursorAt(0, lines[0].textStart);
  827. eq('vim-insert', cm.getOption('keyMap'));
  828. });
  829. // Swapcase commands edit in place and do not modify registers.
  830. testVim('g~w_repeat', function(cm, vim, helpers) {
  831. // Assert that dw does delete newline if it should go to the next line, and
  832. // that repeat works properly.
  833. var curStart = makeCursor(0, 1);
  834. cm.setCursor(curStart);
  835. helpers.doKeys('g', '~', '2', 'w');
  836. eq(' WORD1\nWORD2', cm.getValue());
  837. var register = helpers.getRegisterController().getRegister();
  838. eq('', register.text);
  839. is(!register.linewise);
  840. eqPos(curStart, cm.getCursor());
  841. }, { value: ' word1\nword2' });
  842. testVim('g~g~', function(cm, vim, helpers) {
  843. var curStart = makeCursor(0, 3);
  844. cm.setCursor(curStart);
  845. var expectedLineCount = cm.lineCount();
  846. var expectedValue = cm.getValue().toUpperCase();
  847. helpers.doKeys('2', 'g', '~', '3', 'g', '~');
  848. eq(expectedValue, cm.getValue());
  849. var register = helpers.getRegisterController().getRegister();
  850. eq('', register.text);
  851. is(!register.linewise);
  852. eqPos(curStart, cm.getCursor());
  853. }, { value: ' word1\nword2\nword3\nword4\nword5\nword6' });
  854. testVim('>{motion}', function(cm, vim, helpers) {
  855. cm.setCursor(1, 3);
  856. var expectedLineCount = cm.lineCount();
  857. var expectedValue = ' word1\n word2\nword3 ';
  858. helpers.doKeys('>', 'k');
  859. eq(expectedValue, cm.getValue());
  860. var register = helpers.getRegisterController().getRegister();
  861. eq('', register.text);
  862. is(!register.linewise);
  863. helpers.assertCursorAt(0, 3);
  864. }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
  865. testVim('>>', function(cm, vim, helpers) {
  866. cm.setCursor(0, 3);
  867. var expectedLineCount = cm.lineCount();
  868. var expectedValue = ' word1\n word2\nword3 ';
  869. helpers.doKeys('2', '>', '>');
  870. eq(expectedValue, cm.getValue());
  871. var register = helpers.getRegisterController().getRegister();
  872. eq('', register.text);
  873. is(!register.linewise);
  874. helpers.assertCursorAt(0, 3);
  875. }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
  876. testVim('<{motion}', function(cm, vim, helpers) {
  877. cm.setCursor(1, 3);
  878. var expectedLineCount = cm.lineCount();
  879. var expectedValue = ' word1\nword2\nword3 ';
  880. helpers.doKeys('<', 'k');
  881. eq(expectedValue, cm.getValue());
  882. var register = helpers.getRegisterController().getRegister();
  883. eq('', register.text);
  884. is(!register.linewise);
  885. helpers.assertCursorAt(0, 1);
  886. }, { value: ' word1\n word2\nword3 ', indentUnit: 2 });
  887. testVim('<<', function(cm, vim, helpers) {
  888. cm.setCursor(0, 3);
  889. var expectedLineCount = cm.lineCount();
  890. var expectedValue = ' word1\nword2\nword3 ';
  891. helpers.doKeys('2', '<', '<');
  892. eq(expectedValue, cm.getValue());
  893. var register = helpers.getRegisterController().getRegister();
  894. eq('', register.text);
  895. is(!register.linewise);
  896. helpers.assertCursorAt(0, 1);
  897. }, { value: ' word1\n word2\nword3 ', indentUnit: 2 });
  898. // Edit tests
  899. function testEdit(name, before, pos, edit, after) {
  900. return testVim(name, function(cm, vim, helpers) {
  901. cm.setCursor(0, before.search(pos));
  902. helpers.doKeys.apply(this, edit.split(''));
  903. eq(after, cm.getValue());
  904. }, {value: before});
  905. }
  906. // These Delete tests effectively cover word-wise Change, Visual & Yank.
  907. // Tabs are used as differentiated whitespace to catch edge cases.
  908. // Normal word:
  909. testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz');
  910. testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz');
  911. testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz');
  912. testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz');
  913. testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz');
  914. testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz');
  915. testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz');
  916. testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz');
  917. testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz');
  918. testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz');
  919. testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t');
  920. testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo');
  921. testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.');
  922. testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.');
  923. // Big word:
  924. testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz');
  925. testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz');
  926. testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz');
  927. testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz');
  928. testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz');
  929. testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz');
  930. testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz');
  931. testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz');
  932. testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz');
  933. testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz');
  934. testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t');
  935. testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo');
  936. testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t');
  937. testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo');
  938. // Operator-motion tests
  939. testVim('D', function(cm, vim, helpers) {
  940. var curStart = makeCursor(0, 3);
  941. cm.setCursor(curStart);
  942. helpers.doKeys('D');
  943. eq(' wo\nword2\n word3', cm.getValue());
  944. var register = helpers.getRegisterController().getRegister();
  945. eq('rd1', register.text);
  946. is(!register.linewise);
  947. helpers.assertCursorAt(0, 3);
  948. }, { value: ' word1\nword2\n word3' });
  949. testVim('C', function(cm, vim, helpers) {
  950. var curStart = makeCursor(0, 3);
  951. cm.setCursor(curStart);
  952. helpers.doKeys('C');
  953. eq(' wo\nword2\n word3', cm.getValue());
  954. var register = helpers.getRegisterController().getRegister();
  955. eq('rd1', register.text);
  956. is(!register.linewise);
  957. helpers.assertCursorAt(0, 3);
  958. eq('vim-insert', cm.getOption('keyMap'));
  959. }, { value: ' word1\nword2\n word3' });
  960. testVim('Y', function(cm, vim, helpers) {
  961. var curStart = makeCursor(0, 3);
  962. cm.setCursor(curStart);
  963. helpers.doKeys('Y');
  964. eq(' word1\nword2\n word3', cm.getValue());
  965. var register = helpers.getRegisterController().getRegister();
  966. eq('rd1', register.text);
  967. is(!register.linewise);
  968. helpers.assertCursorAt(0, 3);
  969. }, { value: ' word1\nword2\n word3' });
  970. // Action tests
  971. testVim('ctrl-a', function(cm, vim, helpers) {
  972. cm.setCursor(0, 0);
  973. helpers.doKeys('<C-a>');
  974. eq('-9', cm.getValue());
  975. helpers.assertCursorAt(0, 1);
  976. helpers.doKeys('2','<C-a>');
  977. eq('-7', cm.getValue());
  978. }, {value: '-10'});
  979. testVim('ctrl-x', function(cm, vim, helpers) {
  980. cm.setCursor(0, 0);
  981. helpers.doKeys('<C-x>');
  982. eq('-1', cm.getValue());
  983. helpers.assertCursorAt(0, 1);
  984. helpers.doKeys('2','<C-x>');
  985. eq('-3', cm.getValue());
  986. }, {value: '0'});
  987. testVim('<C-x>/<C-a> search forward', function(cm, vim, helpers) {
  988. ['<C-x>', '<C-a>'].forEach(function(key) {
  989. cm.setCursor(0, 0);
  990. helpers.doKeys(key);
  991. helpers.assertCursorAt(0, 5);
  992. helpers.doKeys('l');
  993. helpers.doKeys(key);
  994. helpers.assertCursorAt(0, 10);
  995. cm.setCursor(0, 11);
  996. helpers.doKeys(key);
  997. helpers.assertCursorAt(0, 11);
  998. });
  999. }, {value: '__jmp1 jmp2 jmp'});
  1000. testVim('a', function(cm, vim, helpers) {
  1001. cm.setCursor(0, 1);
  1002. helpers.doKeys('a');
  1003. helpers.assertCursorAt(0, 2);
  1004. eq('vim-insert', cm.getOption('keyMap'));
  1005. });
  1006. testVim('a_eol', function(cm, vim, helpers) {
  1007. cm.setCursor(0, lines[0].length - 1);
  1008. helpers.doKeys('a');
  1009. helpers.assertCursorAt(0, lines[0].length);
  1010. eq('vim-insert', cm.getOption('keyMap'));
  1011. });
  1012. testVim('i', function(cm, vim, helpers) {
  1013. cm.setCursor(0, 1);
  1014. helpers.doKeys('i');
  1015. helpers.assertCursorAt(0, 1);
  1016. eq('vim-insert', cm.getOption('keyMap'));
  1017. });
  1018. testVim('A', function(cm, vim, helpers) {
  1019. cm.setCursor(0, 0);
  1020. helpers.doKeys('A');
  1021. helpers.assertCursorAt(0, lines[0].length);
  1022. eq('vim-insert', cm.getOption('keyMap'));
  1023. });
  1024. testVim('I', function(cm, vim, helpers) {
  1025. cm.setCursor(0, 4);
  1026. helpers.doKeys('I');
  1027. helpers.assertCursorAt(0, lines[0].textStart);
  1028. eq('vim-insert', cm.getOption('keyMap'));
  1029. });
  1030. testVim('o', function(cm, vim, helpers) {
  1031. cm.setCursor(0, 4);
  1032. helpers.doKeys('o');
  1033. eq('word1\n\nword2', cm.getValue());
  1034. helpers.assertCursorAt(1, 0);
  1035. eq('vim-insert', cm.getOption('keyMap'));
  1036. }, { value: 'word1\nword2' });
  1037. testVim('O', function(cm, vim, helpers) {
  1038. cm.setCursor(0, 4);
  1039. helpers.doKeys('O');
  1040. eq('\nword1\nword2', cm.getValue());
  1041. helpers.assertCursorAt(0, 0);
  1042. eq('vim-insert', cm.getOption('keyMap'));
  1043. }, { value: 'word1\nword2' });
  1044. testVim('J', function(cm, vim, helpers) {
  1045. cm.setCursor(0, 4);
  1046. helpers.doKeys('J');
  1047. var expectedValue = 'word1 word2\nword3\n word4';
  1048. eq(expectedValue, cm.getValue());
  1049. helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1);
  1050. }, { value: 'word1 \n word2\nword3\n word4' });
  1051. testVim('J_repeat', function(cm, vim, helpers) {
  1052. cm.setCursor(0, 4);
  1053. helpers.doKeys('3', 'J');
  1054. var expectedValue = 'word1 word2 word3\n word4';
  1055. eq(expectedValue, cm.getValue());
  1056. helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1);
  1057. }, { value: 'word1 \n word2\nword3\n word4' });
  1058. testVim('p', function(cm, vim, helpers) {
  1059. cm.setCursor(0, 1);
  1060. helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
  1061. helpers.doKeys('p');
  1062. eq('__abc\ndef_', cm.getValue());
  1063. helpers.assertCursorAt(1, 2);
  1064. }, { value: '___' });
  1065. testVim('p_register', function(cm, vim, helpers) {
  1066. cm.setCursor(0, 1);
  1067. helpers.getRegisterController().getRegister('a').set('abc\ndef', false);
  1068. helpers.doKeys('"', 'a', 'p');
  1069. eq('__abc\ndef_', cm.getValue());
  1070. helpers.assertCursorAt(1, 2);
  1071. }, { value: '___' });
  1072. testVim('p_wrong_register', function(cm, vim, helpers) {
  1073. cm.setCursor(0, 1);
  1074. helpers.getRegisterController().getRegister('a').set('abc\ndef', false);
  1075. helpers.doKeys('p');
  1076. eq('___', cm.getValue());
  1077. helpers.assertCursorAt(0, 1);
  1078. }, { value: '___' });
  1079. testVim('p_line', function(cm, vim, helpers) {
  1080. cm.setCursor(0, 1);
  1081. helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);
  1082. helpers.doKeys('2', 'p');
  1083. eq('___\n a\nd\n a\nd', cm.getValue());
  1084. helpers.assertCursorAt(1, 2);
  1085. }, { value: '___' });
  1086. testVim('P', function(cm, vim, helpers) {
  1087. cm.setCursor(0, 1);
  1088. helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
  1089. helpers.doKeys('P');
  1090. eq('_abc\ndef__', cm.getValue());
  1091. helpers.assertCursorAt(1, 3);
  1092. }, { value: '___' });
  1093. testVim('P_line', function(cm, vim, helpers) {
  1094. cm.setCursor(0, 1);
  1095. helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);
  1096. helpers.doKeys('2', 'P');
  1097. eq(' a\nd\n a\nd\n___', cm.getValue());
  1098. helpers.assertCursorAt(0, 2);
  1099. }, { value: '___' });
  1100. testVim('r', function(cm, vim, helpers) {
  1101. cm.setCursor(0, 1);
  1102. helpers.doKeys('3', 'r', 'u');
  1103. eq('wuuuet\nanother', cm.getValue(),'3r failed');
  1104. helpers.assertCursorAt(0, 3);
  1105. cm.setCursor(0, 4);
  1106. helpers.doKeys('v', 'j', 'h', 'r', '<Space>');
  1107. eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed');
  1108. }, { value: 'wordet\nanother' });
  1109. testVim('R', function(cm, vim, helpers) {
  1110. cm.setCursor(0, 1);
  1111. helpers.doKeys('R');
  1112. helpers.assertCursorAt(0, 1);
  1113. eq('vim-replace', cm.getOption('keyMap'));
  1114. is(cm.state.overwrite, 'Setting overwrite state failed');
  1115. });
  1116. testVim('mark', function(cm, vim, helpers) {
  1117. cm.setCursor(2, 2);
  1118. helpers.doKeys('m', 't');
  1119. cm.setCursor(0, 0);
  1120. helpers.doKeys('\'', 't');
  1121. helpers.assertCursorAt(2, 2);
  1122. cm.setCursor(0, 0);
  1123. helpers.doKeys('`', 't');
  1124. helpers.assertCursorAt(2, 2);
  1125. });
  1126. testVim('jumpToMark_next', function(cm, vim, helpers) {
  1127. cm.setCursor(2, 2);
  1128. helpers.doKeys('m', 't');
  1129. cm.setCursor(0, 0);
  1130. helpers.doKeys(']', '`');
  1131. helpers.assertCursorAt(2, 2);
  1132. cm.setCursor(0, 0);
  1133. helpers.doKeys(']', '\'');
  1134. helpers.assertCursorAt(2, 0);
  1135. });
  1136. testVim('jumpToMark_next_repeat', function(cm, vim, helpers) {
  1137. cm.setCursor(2, 2);
  1138. helpers.doKeys('m', 'a');
  1139. cm.setCursor(3, 2);
  1140. helpers.doKeys('m', 'b');
  1141. cm.setCursor(4, 2);
  1142. helpers.doKeys('m', 'c');
  1143. cm.setCursor(0, 0);
  1144. helpers.doKeys('2', ']', '`');
  1145. helpers.assertCursorAt(3, 2);
  1146. cm.setCursor(0, 0);
  1147. helpers.doKeys('2', ']', '\'');
  1148. helpers.assertCursorAt(3, 1);
  1149. });
  1150. testVim('jumpToMark_next_sameline', function(cm, vim, helpers) {
  1151. cm.setCursor(2, 0);
  1152. helpers.doKeys('m', 'a');
  1153. cm.setCursor(2, 4);
  1154. helpers.doKeys('m', 'b');
  1155. cm.setCursor(2, 2);
  1156. helpers.doKeys(']', '`');
  1157. helpers.assertCursorAt(2, 4);
  1158. });
  1159. testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) {
  1160. cm.setCursor(2, 0);
  1161. helpers.doKeys('m', 'a');
  1162. cm.setCursor(4, 0);
  1163. helpers.doKeys(']', '`');
  1164. helpers.assertCursorAt(4, 0);
  1165. });
  1166. testVim('jumpToMark_next_nomark', function(cm, vim, helpers) {
  1167. cm.setCursor(2, 2);
  1168. helpers.doKeys(']', '`');
  1169. helpers.assertCursorAt(2, 2);
  1170. helpers.doKeys(']', '\'');
  1171. helpers.assertCursorAt(2, 0);
  1172. });
  1173. testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) {
  1174. cm.setCursor(2, 2);
  1175. helpers.doKeys('m', 'a');
  1176. cm.setCursor(3, 4);
  1177. helpers.doKeys('m', 'b');
  1178. cm.setCursor(2, 1);
  1179. helpers.doKeys(']', '\'');
  1180. helpers.assertCursorAt(3, 1);
  1181. });
  1182. testVim('jumpToMark_next_action', function(cm, vim, helpers) {
  1183. cm.setCursor(2, 2);
  1184. helpers.doKeys('m', 't');
  1185. cm.setCursor(0, 0);
  1186. helpers.doKeys('d', ']', '`');
  1187. helpers.assertCursorAt(0, 0);
  1188. var actual = cm.getLine(0);
  1189. var expected = 'pop pop 0 1 2 3 4';
  1190. eq(actual, expected, "Deleting while jumping to the next mark failed.");
  1191. });
  1192. testVim('jumpToMark_next_line_action', function(cm, vim, helpers) {
  1193. cm.setCursor(2, 2);
  1194. helpers.doKeys('m', 't');
  1195. cm.setCursor(0, 0);
  1196. helpers.doKeys('d', ']', '\'');
  1197. helpers.assertCursorAt(0, 1);
  1198. var actual = cm.getLine(0);
  1199. var expected = ' (a) [b] {c} '
  1200. eq(actual, expected, "Deleting while jumping to the next mark line failed.");
  1201. });
  1202. testVim('jumpToMark_prev', function(cm, vim, helpers) {
  1203. cm.setCursor(2, 2);
  1204. helpers.doKeys('m', 't');
  1205. cm.setCursor(4, 0);
  1206. helpers.doKeys('[', '`');
  1207. helpers.assertCursorAt(2, 2);
  1208. cm.setCursor(4, 0);
  1209. helpers.doKeys('[', '\'');
  1210. helpers.assertCursorAt(2, 0);
  1211. });
  1212. testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) {
  1213. cm.setCursor(2, 2);
  1214. helpers.doKeys('m', 'a');
  1215. cm.setCursor(3, 2);
  1216. helpers.doKeys('m', 'b');
  1217. cm.setCursor(4, 2);
  1218. helpers.doKeys('m', 'c');
  1219. cm.setCursor(5, 0);
  1220. helpers.doKeys('2', '[', '`');
  1221. helpers.assertCursorAt(3, 2);
  1222. cm.setCursor(5, 0);
  1223. helpers.doKeys('2', '[', '\'');
  1224. helpers.assertCursorAt(3, 1);
  1225. });
  1226. testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) {
  1227. cm.setCursor(2, 0);
  1228. helpers.doKeys('m', 'a');
  1229. cm.setCursor(2, 4);
  1230. helpers.doKeys('m', 'b');
  1231. cm.setCursor(2, 2);
  1232. helpers.doKeys('[', '`');
  1233. helpers.assertCursorAt(2, 0);
  1234. });
  1235. testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) {
  1236. cm.setCursor(4, 4);
  1237. helpers.doKeys('m', 'a');
  1238. cm.setCursor(2, 0);
  1239. helpers.doKeys('[', '`');
  1240. helpers.assertCursorAt(2, 0);
  1241. });
  1242. testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) {
  1243. cm.setCursor(2, 2);
  1244. helpers.doKeys('[', '`');
  1245. helpers.assertCursorAt(2, 2);
  1246. helpers.doKeys('[', '\'');
  1247. helpers.assertCursorAt(2, 0);
  1248. });
  1249. testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) {
  1250. cm.setCursor(2, 2);
  1251. helpers.doKeys('m', 'a');
  1252. cm.setCursor(3, 4);
  1253. helpers.doKeys('m', 'b');
  1254. cm.setCursor(3, 6);
  1255. helpers.doKeys('[', '\'');
  1256. helpers.assertCursorAt(2, 0);
  1257. });
  1258. testVim('delmark_single', function(cm, vim, helpers) {
  1259. cm.setCursor(1, 2);
  1260. helpers.doKeys('m', 't');
  1261. helpers.doEx('delmarks t');
  1262. cm.setCursor(0, 0);
  1263. helpers.doKeys('`', 't');
  1264. helpers.assertCursorAt(0, 0);
  1265. });
  1266. testVim('delmark_range', function(cm, vim, helpers) {
  1267. cm.setCursor(1, 2);
  1268. helpers.doKeys('m', 'a');
  1269. cm.setCursor(2, 2);
  1270. helpers.doKeys('m', 'b');
  1271. cm.setCursor(3, 2);
  1272. helpers.doKeys('m', 'c');
  1273. cm.setCursor(4, 2);
  1274. helpers.doKeys('m', 'd');
  1275. cm.setCursor(5, 2);
  1276. helpers.doKeys('m', 'e');
  1277. helpers.doEx('delmarks b-d');
  1278. cm.setCursor(0, 0);
  1279. helpers.doKeys('`', 'a');
  1280. helpers.assertCursorAt(1, 2);
  1281. helpers.doKeys('`', 'b');
  1282. helpers.assertCursorAt(1, 2);
  1283. helpers.doKeys('`', 'c');
  1284. helpers.assertCursorAt(1, 2);
  1285. helpers.doKeys('`', 'd');
  1286. helpers.assertCursorAt(1, 2);
  1287. helpers.doKeys('`', 'e');
  1288. helpers.assertCursorAt(5, 2);
  1289. });
  1290. testVim('delmark_multi', function(cm, vim, helpers) {
  1291. cm.setCursor(1, 2);
  1292. helpers.doKeys('m', 'a');
  1293. cm.setCursor(2, 2);
  1294. helpers.doKeys('m', 'b');
  1295. cm.setCursor(3, 2);
  1296. helpers.doKeys('m', 'c');
  1297. cm.setCursor(4, 2);
  1298. helpers.doKeys('m', 'd');
  1299. cm.setCursor(5, 2);
  1300. helpers.doKeys('m', 'e');
  1301. helpers.doEx('delmarks bcd');
  1302. cm.setCursor(0, 0);
  1303. helpers.doKeys('`', 'a');
  1304. helpers.assertCursorAt(1, 2);
  1305. helpers.doKeys('`', 'b');
  1306. helpers.assertCursorAt(1, 2);
  1307. helpers.doKeys('`', 'c');
  1308. helpers.assertCursorAt(1, 2);
  1309. helpers.doKeys('`', 'd');
  1310. helpers.assertCursorAt(1, 2);
  1311. helpers.doKeys('`', 'e');
  1312. helpers.assertCursorAt(5, 2);
  1313. });
  1314. testVim('delmark_multi_space', function(cm, vim, helpers) {
  1315. cm.setCursor(1, 2);
  1316. helpers.doKeys('m', 'a');
  1317. cm.setCursor(2, 2);
  1318. helpers.doKeys('m', 'b');
  1319. cm.setCursor(3, 2);
  1320. helpers.doKeys('m', 'c');
  1321. cm.setCursor(4, 2);
  1322. helpers.doKeys('m', 'd');
  1323. cm.setCursor(5, 2);
  1324. helpers.doKeys('m', 'e');
  1325. helpers.doEx('delmarks b c d');
  1326. cm.setCursor(0, 0);
  1327. helpers.doKeys('`', 'a');
  1328. helpers.assertCursorAt(1, 2);
  1329. helpers.doKeys('`', 'b');
  1330. helpers.assertCursorAt(1, 2);
  1331. helpers.doKeys('`', 'c');
  1332. helpers.assertCursorAt(1, 2);
  1333. helpers.doKeys('`', 'd');
  1334. helpers.assertCursorAt(1, 2);
  1335. helpers.doKeys('`', 'e');
  1336. helpers.assertCursorAt(5, 2);
  1337. });
  1338. testVim('delmark_all', function(cm, vim, helpers) {
  1339. cm.setCursor(1, 2);
  1340. helpers.doKeys('m', 'a');
  1341. cm.setCursor(2, 2);
  1342. helpers.doKeys('m', 'b');
  1343. cm.setCursor(3, 2);
  1344. helpers.doKeys('m', 'c');
  1345. cm.setCursor(4, 2);
  1346. helpers.doKeys('m', 'd');
  1347. cm.setCursor(5, 2);
  1348. helpers.doKeys('m', 'e');
  1349. helpers.doEx('delmarks a b-de');
  1350. cm.setCursor(0, 0);
  1351. helpers.doKeys('`', 'a');
  1352. helpers.assertCursorAt(0, 0);
  1353. helpers.doKeys('`', 'b');
  1354. helpers.assertCursorAt(0, 0);
  1355. helpers.doKeys('`', 'c');
  1356. helpers.assertCursorAt(0, 0);
  1357. helpers.doKeys('`', 'd');
  1358. helpers.assertCursorAt(0, 0);
  1359. helpers.doKeys('`', 'e');
  1360. helpers.assertCursorAt(0, 0);
  1361. });
  1362. testVim('visual', function(cm, vim, helpers) {
  1363. helpers.doKeys('l', 'v', 'l', 'l');
  1364. helpers.assertCursorAt(0, 3);
  1365. eqPos(makeCursor(0, 1), cm.getCursor('anchor'));
  1366. helpers.doKeys('d');
  1367. eq('15', cm.getValue());
  1368. }, { value: '12345' });
  1369. testVim('visual_line', function(cm, vim, helpers) {
  1370. helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd');
  1371. eq(' 4\n 5', cm.getValue());
  1372. }, { value: ' 1\n 2\n 3\n 4\n 5' });
  1373. testVim('visual_marks', function(cm, vim, helpers) {
  1374. helpers.doKeys('l', 'v', 'l', 'l', 'v');
  1375. // Test visual mode marks
  1376. cm.setCursor(0, 0);
  1377. helpers.doKeys('\'', '<');
  1378. helpers.assertCursorAt(0, 1);
  1379. helpers.doKeys('\'', '>');
  1380. helpers.assertCursorAt(0, 3);
  1381. });
  1382. testVim('visual_join', function(cm, vim, helpers) {
  1383. helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J');
  1384. eq(' 1 2 3\n 4\n 5', cm.getValue());
  1385. }, { value: ' 1\n 2\n 3\n 4\n 5' });
  1386. testVim('/ and n/N', function(cm, vim, helpers) {
  1387. cm.openDialog = helpers.fakeOpenDialog('match');
  1388. helpers.doKeys('/');
  1389. helpers.assertCursorAt(0, 11);
  1390. helpers.doKeys('n');
  1391. helpers.assertCursorAt(1, 6);
  1392. helpers.doKeys('N');
  1393. helpers.assertCursorAt(0, 11);
  1394. cm.setCursor(0, 0);
  1395. helpers.doKeys('2', '/');
  1396. helpers.assertCursorAt(1, 6);
  1397. }, { value: 'match nope match \n nope Match' });
  1398. testVim('/_case', function(cm, vim, helpers) {
  1399. cm.openDialog = helpers.fakeOpenDialog('Match');
  1400. helpers.doKeys('/');
  1401. helpers.assertCursorAt(1, 6);
  1402. }, { value: 'match nope match \n nope Match' });
  1403. testVim('/_nongreedy', function(cm, vim, helpers) {
  1404. cm.openDialog = helpers.fakeOpenDialog('aa');
  1405. helpers.doKeys('/');
  1406. helpers.assertCursorAt(0, 4);
  1407. helpers.doKeys('n');
  1408. helpers.assertCursorAt(1, 3);
  1409. helpers.doKeys('n');
  1410. helpers.assertCursorAt(0, 0);
  1411. }, { value: 'aaa aa \n a aa'});
  1412. testVim('?_nongreedy', function(cm, vim, helpers) {
  1413. cm.openDialog = helpers.fakeOpenDialog('aa');
  1414. helpers.doKeys('?');
  1415. helpers.assertCursorAt(1, 3);
  1416. helpers.doKeys('n');
  1417. helpers.assertCursorAt(0, 4);
  1418. helpers.doKeys('n');
  1419. helpers.assertCursorAt(0, 0);
  1420. }, { value: 'aaa aa \n a aa'});
  1421. testVim('/_greedy', function(cm, vim, helpers) {
  1422. cm.openDialog = helpers.fakeOpenDialog('a+');
  1423. helpers.doKeys('/');
  1424. helpers.assertCursorAt(0, 4);
  1425. helpers.doKeys('n');
  1426. helpers.assertCursorAt(1, 1);
  1427. helpers.doKeys('n');
  1428. helpers.assertCursorAt(1, 3);
  1429. helpers.doKeys('n');
  1430. helpers.assertCursorAt(0, 0);
  1431. }, { value: 'aaa aa \n a aa'});
  1432. testVim('?_greedy', function(cm, vim, helpers) {
  1433. cm.openDialog = helpers.fakeOpenDialog('a+');
  1434. helpers.doKeys('?');
  1435. helpers.assertCursorAt(1, 3);
  1436. helpers.doKeys('n');
  1437. helpers.assertCursorAt(1, 1);
  1438. helpers.doKeys('n');
  1439. helpers.assertCursorAt(0, 4);
  1440. helpers.doKeys('n');
  1441. helpers.assertCursorAt(0, 0);
  1442. }, { value: 'aaa aa \n a aa'});
  1443. testVim('/_greedy_0_or_more', function(cm, vim, helpers) {
  1444. cm.openDialog = helpers.fakeOpenDialog('a*');
  1445. helpers.doKeys('/');
  1446. helpers.assertCursorAt(0, 3);
  1447. helpers.doKeys('n');
  1448. helpers.assertCursorAt(0, 4);
  1449. helpers.doKeys('n');
  1450. helpers.assertCursorAt(0, 5);
  1451. helpers.doKeys('n');
  1452. helpers.assertCursorAt(1, 0);
  1453. helpers.doKeys('n');
  1454. helpers.assertCursorAt(1, 1);
  1455. helpers.doKeys('n');
  1456. helpers.assertCursorAt(0, 0);
  1457. }, { value: 'aaa aa\n aa'});
  1458. testVim('?_greedy_0_or_more', function(cm, vim, helpers) {
  1459. cm.openDialog = helpers.fakeOpenDialog('a*');
  1460. helpers.doKeys('?');
  1461. helpers.assertCursorAt(1, 1);
  1462. helpers.doKeys('n');
  1463. helpers.assertCursorAt(1, 0);
  1464. helpers.doKeys('n');
  1465. helpers.assertCursorAt(0, 5);
  1466. helpers.doKeys('n');
  1467. helpers.assertCursorAt(0, 4);
  1468. helpers.doKeys('n');
  1469. helpers.assertCursorAt(0, 3);
  1470. helpers.doKeys('n');
  1471. helpers.assertCursorAt(0, 0);
  1472. }, { value: 'aaa aa\n aa'});
  1473. testVim('? and n/N', function(cm, vim, helpers) {
  1474. cm.openDialog = helpers.fakeOpenDialog('match');
  1475. helpers.doKeys('?');
  1476. helpers.assertCursorAt(1, 6);
  1477. helpers.doKeys('n');
  1478. helpers.assertCursorAt(0, 11);
  1479. helpers.doKeys('N');
  1480. helpers.assertCursorAt(1, 6);
  1481. cm.setCursor(0, 0);
  1482. helpers.doKeys('2', '?');
  1483. helpers.assertCursorAt(0, 11);
  1484. }, { value: 'match nope match \n nope Match' });
  1485. testVim('*', function(cm, vim, helpers) {
  1486. cm.setCursor(0, 9);
  1487. helpers.doKeys('*');
  1488. helpers.assertCursorAt(0, 22);
  1489. cm.setCursor(0, 9);
  1490. helpers.doKeys('2', '*');
  1491. helpers.assertCursorAt(1, 8);
  1492. }, { value: 'nomatch match nomatch match \nnomatch Match' });
  1493. testVim('*_no_word', function(cm, vim, helpers) {
  1494. cm.setCursor(0, 0);
  1495. helpers.doKeys('*');
  1496. helpers.assertCursorAt(0, 0);
  1497. }, { value: ' \n match \n' });
  1498. testVim('*_symbol', function(cm, vim, helpers) {
  1499. cm.setCursor(0, 0);
  1500. helpers.doKeys('*');
  1501. helpers.assertCursorAt(1, 0);
  1502. }, { value: ' /}\n/} match \n' });
  1503. testVim('#', function(cm, vim, helpers) {
  1504. cm.setCursor(0, 9);
  1505. helpers.doKeys('#');
  1506. helpers.assertCursorAt(1, 8);
  1507. cm.setCursor(0, 9);
  1508. helpers.doKeys('2', '#');
  1509. helpers.assertCursorAt(0, 22);
  1510. }, { value: 'nomatch match nomatch match \nnomatch Match' });
  1511. testVim('*_seek', function(cm, vim, helpers) {
  1512. // Should skip over space and symbols.
  1513. cm.setCursor(0, 3);
  1514. helpers.doKeys('*');
  1515. helpers.assertCursorAt(0, 22);
  1516. }, { value: ' := match nomatch match \nnomatch Match' });
  1517. testVim('#', function(cm, vim, helpers) {
  1518. // Should skip over space and symbols.
  1519. cm.setCursor(0, 3);
  1520. helpers.doKeys('#');
  1521. helpers.assertCursorAt(1, 8);
  1522. }, { value: ' := match nomatch match \nnomatch Match' });
  1523. testVim('.', function(cm, vim, helpers) {
  1524. cm.setCursor(0, 0);
  1525. helpers.doKeys('2', 'd', 'w');
  1526. helpers.doKeys('.');
  1527. eq('5 6', cm.getValue());
  1528. }, { value: '1 2 3 4 5 6'});
  1529. testVim('._repeat', function(cm, vim, helpers) {
  1530. cm.setCursor(0, 0);
  1531. helpers.doKeys('2', 'd', 'w');
  1532. helpers.doKeys('3', '.');
  1533. eq('6', cm.getValue());
  1534. }, { value: '1 2 3 4 5 6'});
  1535. testVim('f;', function(cm, vim, helpers) {
  1536. cm.setCursor(0, 0);
  1537. helpers.doKeys('f', 'x');
  1538. helpers.doKeys(';');
  1539. helpers.doKeys('2', ';');
  1540. eq(9, cm.getCursor().ch);
  1541. }, { value: '01x3xx678x'});
  1542. testVim('F;', function(cm, vim, helpers) {
  1543. cm.setCursor(0, 8);
  1544. helpers.doKeys('F', 'x');
  1545. helpers.doKeys(';');
  1546. helpers.doKeys('2', ';');
  1547. eq(2, cm.getCursor().ch);
  1548. }, { value: '01x3xx6x8x'});
  1549. testVim('t;', function(cm, vim, helpers) {
  1550. cm.setCursor(0, 0);
  1551. helpers.doKeys('t', 'x');
  1552. helpers.doKeys(';');
  1553. helpers.doKeys('2', ';');
  1554. eq(8, cm.getCursor().ch);
  1555. }, { value: '01x3xx678x'});
  1556. testVim('T;', function(cm, vim, helpers) {
  1557. cm.setCursor(0, 9);
  1558. helpers.doKeys('T', 'x');
  1559. helpers.doKeys(';');
  1560. helpers.doKeys('2', ';');
  1561. eq(2, cm.getCursor().ch);
  1562. }, { value: '0xx3xx678x'});
  1563. testVim('f,', function(cm, vim, helpers) {
  1564. cm.setCursor(0, 6);
  1565. helpers.doKeys('f', 'x');
  1566. helpers.doKeys(',');
  1567. helpers.doKeys('2', ',');
  1568. eq(2, cm.getCursor().ch);
  1569. }, { value: '01x3xx678x'});
  1570. testVim('F,', function(cm, vim, helpers) {
  1571. cm.setCursor(0, 3);
  1572. helpers.doKeys('F', 'x');
  1573. helpers.doKeys(',');
  1574. helpers.doKeys('2', ',');
  1575. eq(9, cm.getCursor().ch);
  1576. }, { value: '01x3xx678x'});
  1577. testVim('t,', function(cm, vim, helpers) {
  1578. cm.setCursor(0, 6);
  1579. helpers.doKeys('t', 'x');
  1580. helpers.doKeys(',');
  1581. helpers.doKeys('2', ',');
  1582. eq(3, cm.getCursor().ch);
  1583. }, { value: '01x3xx678x'});
  1584. testVim('T,', function(cm, vim, helpers) {
  1585. cm.setCursor(0, 4);
  1586. helpers.doKeys('T', 'x');
  1587. helpers.doKeys(',');
  1588. helpers.doKeys('2', ',');
  1589. eq(8, cm.getCursor().ch);
  1590. }, { value: '01x3xx67xx'});
  1591. testVim('fd,;', function(cm, vim, helpers) {
  1592. cm.setCursor(0, 0);
  1593. helpers.doKeys('f', '4');
  1594. cm.setCursor(0, 0);
  1595. helpers.doKeys('d', ';');
  1596. eq('56789', cm.getValue());
  1597. helpers.doKeys('u');
  1598. cm.setCursor(0, 9);
  1599. helpers.doKeys('d', ',');
  1600. eq('01239', cm.getValue());
  1601. }, { value: '0123456789'});
  1602. testVim('Fd,;', function(cm, vim, helpers) {
  1603. cm.setCursor(0, 9);
  1604. helpers.doKeys('F', '4');
  1605. cm.setCursor(0, 9);
  1606. helpers.doKeys('d', ';');
  1607. eq('01239', cm.getValue());
  1608. helpers.doKeys('u');
  1609. cm.setCursor(0, 0);
  1610. helpers.doKeys('d', ',');
  1611. eq('56789', cm.getValue());
  1612. }, { value: '0123456789'});
  1613. testVim('td,;', function(cm, vim, helpers) {
  1614. cm.setCursor(0, 0);
  1615. helpers.doKeys('t', '4');
  1616. cm.setCursor(0, 0);
  1617. helpers.doKeys('d', ';');
  1618. eq('456789', cm.getValue());
  1619. helpers.doKeys('u');
  1620. cm.setCursor(0, 9);
  1621. helpers.doKeys('d', ',');
  1622. eq('012349', cm.getValue());
  1623. }, { value: '0123456789'});
  1624. testVim('Td,;', function(cm, vim, helpers) {
  1625. cm.setCursor(0, 9);
  1626. helpers.doKeys('T', '4');
  1627. cm.setCursor(0, 9);
  1628. helpers.doKeys('d', ';');
  1629. eq('012349', cm.getValue());
  1630. helpers.doKeys('u');
  1631. cm.setCursor(0, 0);
  1632. helpers.doKeys('d', ',');
  1633. eq('456789', cm.getValue());
  1634. }, { value: '0123456789'});
  1635. testVim('fc,;', function(cm, vim, helpers) {
  1636. cm.setCursor(0, 0);
  1637. helpers.doKeys('f', '4');
  1638. cm.setCursor(0, 0);
  1639. helpers.doKeys('c', ';', 'Esc');
  1640. eq('56789', cm.getValue());
  1641. helpers.doKeys('u');
  1642. cm.setCursor(0, 9);
  1643. helpers.doKeys('c', ',');
  1644. eq('01239', cm.getValue());
  1645. }, { value: '0123456789'});
  1646. testVim('Fc,;', function(cm, vim, helpers) {
  1647. cm.setCursor(0, 9);
  1648. helpers.doKeys('F', '4');
  1649. cm.setCursor(0, 9);
  1650. helpers.doKeys('c', ';', 'Esc');
  1651. eq('01239', cm.getValue());
  1652. helpers.doKeys('u');
  1653. cm.setCursor(0, 0);
  1654. helpers.doKeys('c', ',');
  1655. eq('56789', cm.getValue());
  1656. }, { value: '0123456789'});
  1657. testVim('tc,;', function(cm, vim, helpers) {
  1658. cm.setCursor(0, 0);
  1659. helpers.doKeys('t', '4');
  1660. cm.setCursor(0, 0);
  1661. helpers.doKeys('c', ';', 'Esc');
  1662. eq('456789', cm.getValue());
  1663. helpers.doKeys('u');
  1664. cm.setCursor(0, 9);
  1665. helpers.doKeys('c', ',');
  1666. eq('012349', cm.getValue());
  1667. }, { value: '0123456789'});
  1668. testVim('Tc,;', function(cm, vim, helpers) {
  1669. cm.setCursor(0, 9);
  1670. helpers.doKeys('T', '4');
  1671. cm.setCursor(0, 9);
  1672. helpers.doKeys('c', ';', 'Esc');
  1673. eq('012349', cm.getValue());
  1674. helpers.doKeys('u');
  1675. cm.setCursor(0, 0);
  1676. helpers.doKeys('c', ',');
  1677. eq('456789', cm.getValue());
  1678. }, { value: '0123456789'});
  1679. testVim('fy,;', function(cm, vim, helpers) {
  1680. cm.setCursor(0, 0);
  1681. helpers.doKeys('f', '4');
  1682. cm.setCursor(0, 0);
  1683. helpers.doKeys('y', ';', 'P');
  1684. eq('012340123456789', cm.getValue());
  1685. helpers.doKeys('u');
  1686. cm.setCursor(0, 9);
  1687. helpers.doKeys('y', ',', 'P');
  1688. eq('012345678456789', cm.getValue());
  1689. }, { value: '0123456789'});
  1690. testVim('Fy,;', function(cm, vim, helpers) {
  1691. cm.setCursor(0, 9);
  1692. helpers.doKeys('F', '4');
  1693. cm.setCursor(0, 9);
  1694. helpers.doKeys('y', ';', 'p');
  1695. eq('012345678945678', cm.getValue());
  1696. helpers.doKeys('u');
  1697. cm.setCursor(0, 0);
  1698. helpers.doKeys('y', ',', 'P');
  1699. eq('012340123456789', cm.getValue());
  1700. }, { value: '0123456789'});
  1701. testVim('ty,;', function(cm, vim, helpers) {
  1702. cm.setCursor(0, 0);
  1703. helpers.doKeys('t', '4');
  1704. cm.setCursor(0, 0);
  1705. helpers.doKeys('y', ';', 'P');
  1706. eq('01230123456789', cm.getValue());
  1707. helpers.doKeys('u');
  1708. cm.setCursor(0, 9);
  1709. helpers.doKeys('y', ',', 'p');
  1710. eq('01234567895678', cm.getValue());
  1711. }, { value: '0123456789'});
  1712. testVim('Ty,;', function(cm, vim, helpers) {
  1713. cm.setCursor(0, 9);
  1714. helpers.doKeys('T', '4');
  1715. cm.setCursor(0, 9);
  1716. helpers.doKeys('y', ';', 'p');
  1717. eq('01234567895678', cm.getValue());
  1718. helpers.doKeys('u');
  1719. cm.setCursor(0, 0);
  1720. helpers.doKeys('y', ',', 'P');
  1721. eq('01230123456789', cm.getValue());
  1722. }, { value: '0123456789'});
  1723. testVim('HML', function(cm, vim, helpers) {
  1724. var lines = 35;
  1725. var textHeight = cm.defaultTextHeight();
  1726. cm.setSize(600, lines*textHeight);
  1727. cm.setCursor(120, 0);
  1728. helpers.doKeys('H');
  1729. helpers.assertCursorAt(86, 2);
  1730. helpers.doKeys('L');
  1731. helpers.assertCursorAt(120, 4);
  1732. helpers.doKeys('M');
  1733. helpers.assertCursorAt(103,4);
  1734. }, { value: (function(){
  1735. var lines = new Array(100);
  1736. var upper = ' xx\n';
  1737. var lower = ' xx\n';
  1738. upper = lines.join(upper);
  1739. lower = lines.join(lower);
  1740. return upper + lower;
  1741. })()});
  1742. var zVals = ['zb','zz','zt','z-','z.','z<CR>'].map(function(e, idx){
  1743. var lineNum = 250;
  1744. var lines = 35;
  1745. testVim(e, function(cm, vim, helpers) {
  1746. var k1 = e[0];
  1747. var k2 = e.substring(1);
  1748. var textHeight = cm.defaultTextHeight();
  1749. cm.setSize(600, lines*textHeight);
  1750. cm.setCursor(lineNum, 0);
  1751. helpers.doKeys(k1, k2);
  1752. zVals[idx] = cm.getScrollInfo().top;
  1753. }, { value: (function(){
  1754. return new Array(500).join('\n');
  1755. })()});
  1756. });
  1757. testVim('zb<zz', function(cm, vim, helpers){
  1758. eq(zVals[0]<zVals[1], true);
  1759. });
  1760. testVim('zz<zt', function(cm, vim, helpers){
  1761. eq(zVals[1]<zVals[2], true);
  1762. });
  1763. testVim('zb==z-', function(cm, vim, helpers){
  1764. eq(zVals[0], zVals[3]);
  1765. });
  1766. testVim('zz==z.', function(cm, vim, helpers){
  1767. eq(zVals[1], zVals[4]);
  1768. });
  1769. testVim('zt==z<CR>', function(cm, vim, helpers){
  1770. eq(zVals[2], zVals[5]);
  1771. });
  1772. var squareBracketMotionSandbox = ''+
  1773. '({\n'+//0
  1774. ' ({\n'+//11
  1775. ' /*comment {\n'+//2
  1776. ' */(\n'+//3
  1777. '#else \n'+//4
  1778. ' /* )\n'+//5
  1779. '#if }\n'+//6
  1780. ' )}*/\n'+//7
  1781. ')}\n'+//8
  1782. '{}\n'+//9
  1783. '#else {{\n'+//10
  1784. '{}\n'+//11
  1785. '}\n'+//12
  1786. '{\n'+//13
  1787. '#endif\n'+//14
  1788. '}\n'+//15
  1789. '}\n'+//16
  1790. '#else';//17
  1791. testVim('[[, ]]', function(cm, vim, helpers) {
  1792. cm.setCursor(0, 0);
  1793. helpers.doKeys(']', ']');
  1794. helpers.assertCursorAt(9,0);
  1795. helpers.doKeys('2', ']', ']');
  1796. helpers.assertCursorAt(13,0);
  1797. helpers.doKeys(']', ']');
  1798. helpers.assertCursorAt(17,0);
  1799. helpers.doKeys('[', '[');
  1800. helpers.assertCursorAt(13,0);
  1801. helpers.doKeys('2', '[', '[');
  1802. helpers.assertCursorAt(9,0);
  1803. helpers.doKeys('[', '[');
  1804. helpers.assertCursorAt(0,0);
  1805. }, { value: squareBracketMotionSandbox});
  1806. testVim('[], ][', function(cm, vim, helpers) {
  1807. cm.setCursor(0, 0);
  1808. helpers.doKeys(']', '[');
  1809. helpers.assertCursorAt(12,0);
  1810. helpers.doKeys('2', ']', '[');
  1811. helpers.assertCursorAt(16,0);
  1812. helpers.doKeys(']', '[');
  1813. helpers.assertCursorAt(17,0);
  1814. helpers.doKeys('[', ']');
  1815. helpers.assertCursorAt(16,0);
  1816. helpers.doKeys('2', '[', ']');
  1817. helpers.assertCursorAt(12,0);
  1818. helpers.doKeys('[', ']');
  1819. helpers.assertCursorAt(0,0);
  1820. }, { value: squareBracketMotionSandbox});
  1821. testVim('[{, ]}', function(cm, vim, helpers) {
  1822. cm.setCursor(4, 10);
  1823. helpers.doKeys('[', '{');
  1824. helpers.assertCursorAt(2,12);
  1825. helpers.doKeys('2', '[', '{');
  1826. helpers.assertCursorAt(0,1);
  1827. cm.setCursor(4, 10);
  1828. helpers.doKeys(']', '}');
  1829. helpers.assertCursorAt(6,11);
  1830. helpers.doKeys('2', ']', '}');
  1831. helpers.assertCursorAt(8,1);
  1832. cm.setCursor(0,1);
  1833. helpers.doKeys(']', '}');
  1834. helpers.assertCursorAt(8,1);
  1835. helpers.doKeys('[', '{');
  1836. helpers.assertCursorAt(0,1);
  1837. }, { value: squareBracketMotionSandbox});
  1838. testVim('[(, ])', function(cm, vim, helpers) {
  1839. cm.setCursor(4, 10);
  1840. helpers.doKeys('[', '(');
  1841. helpers.assertCursorAt(3,14);
  1842. helpers.doKeys('2', '[', '(');
  1843. helpers.assertCursorAt(0,0);
  1844. cm.setCursor(4, 10);
  1845. helpers.doKeys(']', ')');
  1846. helpers.assertCursorAt(5,11);
  1847. helpers.doKeys('2', ']', ')');
  1848. helpers.assertCursorAt(8,0);
  1849. helpers.doKeys('[', '(');
  1850. helpers.assertCursorAt(0,0);
  1851. helpers.doKeys(']', ')');
  1852. helpers.assertCursorAt(8,0);
  1853. }, { value: squareBracketMotionSandbox});
  1854. testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) {
  1855. ['*', '/'].forEach(function(key){
  1856. cm.setCursor(7, 0);
  1857. helpers.doKeys('2', '[', key);
  1858. helpers.assertCursorAt(2,2);
  1859. helpers.doKeys('2', ']', key);
  1860. helpers.assertCursorAt(7,5);
  1861. });
  1862. }, { value: squareBracketMotionSandbox});
  1863. testVim('[#, ]#', function(cm, vim, helpers) {
  1864. cm.setCursor(10, 3);
  1865. helpers.doKeys('2', '[', '#');
  1866. helpers.assertCursorAt(4,0);
  1867. helpers.doKeys('5', ']', '#');
  1868. helpers.assertCursorAt(17,0);
  1869. cm.setCursor(10, 3);
  1870. helpers.doKeys(']', '#');
  1871. helpers.assertCursorAt(14,0);
  1872. }, { value: squareBracketMotionSandbox});
  1873. testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) {
  1874. cm.setCursor(11, 0);
  1875. helpers.doKeys('[', 'm');
  1876. helpers.assertCursorAt(10,7);
  1877. helpers.doKeys('4', '[', 'm');
  1878. helpers.assertCursorAt(1,3);
  1879. helpers.doKeys('5', ']', 'm');
  1880. helpers.assertCursorAt(11,0);
  1881. helpers.doKeys('[', 'M');
  1882. helpers.assertCursorAt(9,1);
  1883. helpers.doKeys('3', ']', 'M');
  1884. helpers.assertCursorAt(15,0);
  1885. helpers.doKeys('5', '[', 'M');
  1886. helpers.assertCursorAt(7,3);
  1887. }, { value: squareBracketMotionSandbox});
  1888. // Ex mode tests
  1889. testVim('ex_go_to_line', function(cm, vim, helpers) {
  1890. cm.setCursor(0, 0);
  1891. helpers.doEx('4');
  1892. helpers.assertCursorAt(3, 0);
  1893. }, { value: 'a\nb\nc\nd\ne\n'});
  1894. testVim('ex_write', function(cm, vim, helpers) {
  1895. var tmp = CodeMirror.commands.save;
  1896. var written;
  1897. var actualCm;
  1898. CodeMirror.commands.save = function(cm) {
  1899. written = true;
  1900. actualCm = cm;
  1901. };
  1902. // Test that w, wr, wri ... write all trigger :write.
  1903. var command = 'write';
  1904. for (var i = 1; i < command.length; i++) {
  1905. written = false;
  1906. actualCm = null;
  1907. helpers.doEx(command.substring(0, i));
  1908. eq(written, true);
  1909. eq(actualCm, cm);
  1910. }
  1911. CodeMirror.commands.save = tmp;
  1912. });
  1913. testVim('ex_substitute_same_line', function(cm, vim, helpers) {
  1914. cm.setCursor(1, 0);
  1915. helpers.doEx('s/one/two');
  1916. eq('one one\n two two', cm.getValue());
  1917. }, { value: 'one one\n one one'});
  1918. testVim('ex_substitute_global', function(cm, vim, helpers) {
  1919. cm.setCursor(1, 0);
  1920. helpers.doEx('%s/one/two');
  1921. eq('two two\n two two', cm.getValue());
  1922. }, { value: 'one one\n one one'});
  1923. testVim('ex_substitute_input_range', function(cm, vim, helpers) {
  1924. cm.setCursor(1, 0);
  1925. helpers.doEx('1,3s/\\d/0');
  1926. eq('0\n0\n0\n4', cm.getValue());
  1927. }, { value: '1\n2\n3\n4' });
  1928. testVim('ex_substitute_visual_range', function(cm, vim, helpers) {
  1929. cm.setCursor(1, 0);
  1930. // Set last visual mode selection marks '< and '> at lines 2 and 4
  1931. helpers.doKeys('V', '2', 'j', 'v');
  1932. helpers.doEx('\'<,\'>s/\\d/0');
  1933. eq('1\n0\n0\n0\n5', cm.getValue());
  1934. }, { value: '1\n2\n3\n4\n5' });
  1935. testVim('ex_substitute_capture', function(cm, vim, helpers) {
  1936. cm.setCursor(1, 0);
  1937. helpers.doEx('s/(\\d+)/$1$1/')
  1938. eq('a1111 a1212 a1313', cm.getValue());
  1939. }, { value: 'a11 a12 a13' });
  1940. testVim('ex_substitute_empty_query', function(cm, vim, helpers) {
  1941. // If the query is empty, use last query.
  1942. cm.setCursor(1, 0);
  1943. cm.openDialog = helpers.fakeOpenDialog('1');
  1944. helpers.doKeys('/');
  1945. helpers.doEx('s//b');
  1946. eq('abb ab2 ab3', cm.getValue());
  1947. }, { value: 'a11 a12 a13' });
  1948. testVim('ex_substitute_count', function(cm, vim, helpers) {
  1949. cm.setCursor(1, 0);
  1950. helpers.doEx('s/\\d/0/i 2');
  1951. eq('1\n0\n0\n4', cm.getValue());
  1952. }, { value: '1\n2\n3\n4' });
  1953. testVim('ex_substitute_count_with_range', function(cm, vim, helpers) {
  1954. cm.setCursor(1, 0);
  1955. helpers.doEx('1,3s/\\d/0/ 3');
  1956. eq('1\n2\n0\n0', cm.getValue());
  1957. }, { value: '1\n2\n3\n4' });
  1958. //:noh should clear highlighting of search-results but allow to resume search through n
  1959. testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) {
  1960. cm.openDialog = helpers.fakeOpenDialog('match');
  1961. helpers.doKeys('?');
  1962. helpers.doEx('noh');
  1963. eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared');
  1964. helpers.doKeys('n');
  1965. helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting');
  1966. }, { value: 'match nope match \n nope Match' });
  1967. // TODO: Reset key maps after each test.
  1968. testVim('ex_map_key2key', function(cm, vim, helpers) {
  1969. helpers.doEx('map a x');
  1970. helpers.doKeys('a');
  1971. helpers.assertCursorAt(0, 0);
  1972. eq('bc', cm.getValue());
  1973. }, { value: 'abc' });
  1974. testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) {
  1975. helpers.doEx('map ; :');
  1976. var dialogOpened = false;
  1977. cm.openDialog = function() {
  1978. dialogOpened = true;
  1979. }
  1980. helpers.doKeys(';');
  1981. eq(dialogOpened, true);
  1982. });
  1983. testVim('ex_map_ex2key:', function(cm, vim, helpers) {
  1984. helpers.doEx('map :del x');
  1985. helpers.doEx('del');
  1986. helpers.assertCursorAt(0, 0);
  1987. eq('bc', cm.getValue());
  1988. }, { value: 'abc' });
  1989. testVim('ex_map_ex2ex', function(cm, vim, helpers) {
  1990. helpers.doEx('map :del :w');
  1991. var tmp = CodeMirror.commands.save;
  1992. var written = false;
  1993. var actualCm;
  1994. CodeMirror.commands.save = function(cm) {
  1995. written = true;
  1996. actualCm = cm;
  1997. };
  1998. helpers.doEx('del');
  1999. CodeMirror.commands.save = tmp;
  2000. eq(written, true);
  2001. eq(actualCm, cm);
  2002. });
  2003. testVim('ex_map_key2ex', function(cm, vim, helpers) {
  2004. helpers.doEx('map a :w');
  2005. var tmp = CodeMirror.commands.save;
  2006. var written = false;
  2007. var actualCm;
  2008. CodeMirror.commands.save = function(cm) {
  2009. written = true;
  2010. actualCm = cm;
  2011. };
  2012. helpers.doKeys('a');
  2013. CodeMirror.commands.save = tmp;
  2014. eq(written, true);
  2015. eq(actualCm, cm);
  2016. });
  2017. // Testing registration of functions as ex-commands and mapping to <Key>-keys
  2018. testVim('ex_api_test', function(cm, vim, helpers) {
  2019. var res=false;
  2020. var val='from';
  2021. CodeMirror.Vim.defineEx('extest','ext',function(cm,params){
  2022. if(params.args)val=params.args[0];
  2023. else res=true;
  2024. });
  2025. helpers.doEx(':ext to');
  2026. eq(val,'to','Defining ex-command failed');
  2027. CodeMirror.Vim.map('<C-CR><Space>',':ext');
  2028. helpers.doKeys('<C-CR>','<Space>');
  2029. is(res,'Mapping to key failed');
  2030. });
  2031. // For now, this test needs to be last because it messes up : for future tests.
  2032. testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) {
  2033. helpers.doEx('map : x');
  2034. helpers.doKeys(':');
  2035. helpers.assertCursorAt(0, 0);
  2036. eq('bc', cm.getValue());
  2037. }, { value: 'abc' });