vim_test.js 122 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520
  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 forEach(arr, func) {
  95. for (var i = 0; i < arr.length; i++) {
  96. func(arr[i], i, arr);
  97. }
  98. }
  99. function testVim(name, run, opts, expectedFail) {
  100. var vimOpts = {
  101. lineNumbers: true,
  102. vimMode: true,
  103. showCursorWhenSelecting: true,
  104. value: code
  105. };
  106. for (var prop in opts) {
  107. if (opts.hasOwnProperty(prop)) {
  108. vimOpts[prop] = opts[prop];
  109. }
  110. }
  111. return test('vim_' + name, function() {
  112. var place = document.getElementById("testground");
  113. var cm = CodeMirror(place, vimOpts);
  114. var vim = CodeMirror.Vim.maybeInitVimState_(cm);
  115. function doKeysFn(cm) {
  116. return function(args) {
  117. if (args instanceof Array) {
  118. arguments = args;
  119. }
  120. for (var i = 0; i < arguments.length; i++) {
  121. CodeMirror.Vim.handleKey(cm, arguments[i]);
  122. }
  123. }
  124. }
  125. function doInsertModeKeysFn(cm) {
  126. return function(args) {
  127. if (args instanceof Array) { arguments = args; }
  128. function executeHandler(handler) {
  129. if (typeof handler == 'string') {
  130. CodeMirror.commands[handler](cm);
  131. } else {
  132. handler(cm);
  133. }
  134. return true;
  135. }
  136. for (var i = 0; i < arguments.length; i++) {
  137. var key = arguments[i];
  138. // Find key in keymap and handle.
  139. var handled = CodeMirror.lookupKey(key, ['vim-insert'], executeHandler);
  140. // Record for insert mode.
  141. if (handled === true && cm.state.vim.insertMode && arguments[i] != 'Esc') {
  142. var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;
  143. if (lastChange) {
  144. lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));
  145. }
  146. }
  147. }
  148. }
  149. }
  150. function doExFn(cm) {
  151. return function(command) {
  152. cm.openDialog = helpers.fakeOpenDialog(command);
  153. helpers.doKeys(':');
  154. }
  155. }
  156. function assertCursorAtFn(cm) {
  157. return function(line, ch) {
  158. var pos;
  159. if (ch == null && typeof line.line == 'number') {
  160. pos = line;
  161. } else {
  162. pos = makeCursor(line, ch);
  163. }
  164. eqPos(pos, cm.getCursor());
  165. }
  166. }
  167. function fakeOpenDialog(result) {
  168. return function(text, callback) {
  169. return callback(result);
  170. }
  171. }
  172. function fakeOpenNotification(matcher) {
  173. return function(text) {
  174. matcher(text);
  175. }
  176. }
  177. var helpers = {
  178. doKeys: doKeysFn(cm),
  179. // Warning: Only emulates keymap events, not character insertions. Use
  180. // replaceRange to simulate character insertions.
  181. // Keys are in CodeMirror format, NOT vim format.
  182. doInsertModeKeys: doInsertModeKeysFn(cm),
  183. doEx: doExFn(cm),
  184. assertCursorAt: assertCursorAtFn(cm),
  185. fakeOpenDialog: fakeOpenDialog,
  186. fakeOpenNotification: fakeOpenNotification,
  187. getRegisterController: function() {
  188. return CodeMirror.Vim.getRegisterController();
  189. }
  190. }
  191. CodeMirror.Vim.resetVimGlobalState_();
  192. var successful = false;
  193. var savedOpenNotification = cm.openNotification;
  194. try {
  195. run(cm, vim, helpers);
  196. successful = true;
  197. } finally {
  198. cm.openNotification = savedOpenNotification;
  199. if (!successful || verbose) {
  200. place.style.visibility = "visible";
  201. } else {
  202. place.removeChild(cm.getWrapperElement());
  203. }
  204. }
  205. }, expectedFail);
  206. };
  207. testVim('qq@q', function(cm, vim, helpers) {
  208. cm.setCursor(0, 0);
  209. helpers.doKeys('q', 'q', 'l', 'l', 'q');
  210. helpers.assertCursorAt(0,2);
  211. helpers.doKeys('@', 'q');
  212. helpers.assertCursorAt(0,4);
  213. }, { value: ' '});
  214. testVim('@@', function(cm, vim, helpers) {
  215. cm.setCursor(0, 0);
  216. helpers.doKeys('q', 'q', 'l', 'l', 'q');
  217. helpers.assertCursorAt(0,2);
  218. helpers.doKeys('@', 'q');
  219. helpers.assertCursorAt(0,4);
  220. helpers.doKeys('@', '@');
  221. helpers.assertCursorAt(0,6);
  222. }, { value: ' '});
  223. var jumplistScene = ''+
  224. 'word\n'+
  225. '(word)\n'+
  226. '{word\n'+
  227. 'word.\n'+
  228. '\n'+
  229. 'word search\n'+
  230. '}word\n'+
  231. 'word\n'+
  232. 'word\n';
  233. function testJumplist(name, keys, endPos, startPos, dialog) {
  234. endPos = makeCursor(endPos[0], endPos[1]);
  235. startPos = makeCursor(startPos[0], startPos[1]);
  236. testVim(name, function(cm, vim, helpers) {
  237. CodeMirror.Vim.resetVimGlobalState_();
  238. if(dialog)cm.openDialog = helpers.fakeOpenDialog('word');
  239. cm.setCursor(startPos);
  240. helpers.doKeys.apply(null, keys);
  241. helpers.assertCursorAt(endPos);
  242. }, {value: jumplistScene});
  243. };
  244. testJumplist('jumplist_H', ['H', '<C-o>'], [5,2], [5,2]);
  245. testJumplist('jumplist_M', ['M', '<C-o>'], [2,2], [2,2]);
  246. testJumplist('jumplist_L', ['L', '<C-o>'], [2,2], [2,2]);
  247. testJumplist('jumplist_[[', ['[', '[', '<C-o>'], [5,2], [5,2]);
  248. testJumplist('jumplist_]]', [']', ']', '<C-o>'], [2,2], [2,2]);
  249. testJumplist('jumplist_G', ['G', '<C-o>'], [5,2], [5,2]);
  250. testJumplist('jumplist_gg', ['g', 'g', '<C-o>'], [5,2], [5,2]);
  251. testJumplist('jumplist_%', ['%', '<C-o>'], [1,5], [1,5]);
  252. testJumplist('jumplist_{', ['{', '<C-o>'], [1,5], [1,5]);
  253. testJumplist('jumplist_}', ['}', '<C-o>'], [1,5], [1,5]);
  254. testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', '<C-i>'], [1,0], [1,5]);
  255. testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', '<C-i>'], [1,5], [1,5]);
  256. testJumplist('jumplist_*_cachedCursor', ['*', '<C-o>'], [1,3], [1,3]);
  257. testJumplist('jumplist_#_cachedCursor', ['#', '<C-o>'], [1,3], [1,3]);
  258. testJumplist('jumplist_n', ['#', 'n', '<C-o>'], [1,1], [2,3]);
  259. testJumplist('jumplist_N', ['#', 'N', '<C-o>'], [1,1], [2,3]);
  260. testJumplist('jumplist_repeat_<c-o>', ['*', '*', '*', '3', '<C-o>'], [2,3], [2,3]);
  261. testJumplist('jumplist_repeat_<c-i>', ['*', '*', '*', '3', '<C-o>', '2', '<C-i>'], [5,0], [2,3]);
  262. testJumplist('jumplist_repeated_motion', ['3', '*', '<C-o>'], [2,3], [2,3]);
  263. testJumplist('jumplist_/', ['/', '<C-o>'], [2,3], [2,3], 'dialog');
  264. testJumplist('jumplist_?', ['?', '<C-o>'], [2,3], [2,3], 'dialog');
  265. testJumplist('jumplist_skip_delted_mark<c-o>',
  266. ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-o>', '<C-o>'],
  267. [0,2], [0,2]);
  268. testJumplist('jumplist_skip_delted_mark<c-i>',
  269. ['*', 'n', 'n', 'k', 'd', 'k', '<C-o>', '<C-i>', '<C-i>'],
  270. [1,0], [0,2]);
  271. /**
  272. * @param name Name of the test
  273. * @param keys An array of keys or a string with a single key to simulate.
  274. * @param endPos The expected end position of the cursor.
  275. * @param startPos The position the cursor should start at, defaults to 0, 0.
  276. */
  277. function testMotion(name, keys, endPos, startPos) {
  278. testVim(name, function(cm, vim, helpers) {
  279. if (!startPos) {
  280. startPos = { line: 0, ch: 0 };
  281. }
  282. cm.setCursor(startPos);
  283. helpers.doKeys(keys);
  284. helpers.assertCursorAt(endPos);
  285. });
  286. };
  287. function makeCursor(line, ch) {
  288. return { line: line, ch: ch };
  289. };
  290. function offsetCursor(cur, offsetLine, offsetCh) {
  291. return { line: cur.line + offsetLine, ch: cur.ch + offsetCh };
  292. };
  293. // Motion tests
  294. testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4));
  295. testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4));
  296. testMotion('h', 'h', makeCursor(0, 0), word1.start);
  297. testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end);
  298. testMotion('l', 'l', makeCursor(0, 1));
  299. testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2));
  300. testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end);
  301. testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end);
  302. testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument);
  303. testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end);
  304. testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4));
  305. testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4));
  306. testMotion('w', 'w', word1.start);
  307. testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2));
  308. testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51));
  309. testMotion('w_repeat', ['2', 'w'], word2.start);
  310. testMotion('w_wrap', ['w'], word3.start, word2.start);
  311. testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument);
  312. testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0));
  313. testMotion('W', 'W', bigWord1.start);
  314. testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start);
  315. testMotion('e', 'e', word1.end);
  316. testMotion('e_repeat', ['2', 'e'], word2.end);
  317. testMotion('e_wrap', 'e', word3.end, word2.end);
  318. testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument);
  319. testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0));
  320. testMotion('b', 'b', word3.start, word3.end);
  321. testMotion('b_repeat', ['2', 'b'], word2.start, word3.end);
  322. testMotion('b_wrap', 'b', word2.start, word3.start);
  323. testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0));
  324. testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument);
  325. testMotion('ge', ['g', 'e'], word2.end, word3.end);
  326. testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start);
  327. testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start);
  328. testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0),
  329. makeCursor(0, 0));
  330. testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument);
  331. testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart),
  332. makeCursor(3, 1));
  333. testMotion('gg_repeat', ['3', 'g', 'g'],
  334. makeCursor(lines[2].line, lines[2].textStart));
  335. testMotion('G', 'G',
  336. makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart),
  337. makeCursor(3, 1));
  338. testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line,
  339. lines[2].textStart));
  340. // TODO: Make the test code long enough to test Ctrl-F and Ctrl-B.
  341. testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8));
  342. testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8));
  343. testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8));
  344. testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4));
  345. testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8));
  346. testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1));
  347. testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1),
  348. makeCursor(0, 3));
  349. testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0));
  350. testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]);
  351. testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0));
  352. testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1),
  353. makeCursor(charLine.line, 0));
  354. testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1),
  355. pChars[0]);
  356. testMotion('F', ['F', 'p'], pChars[0], pChars[1]);
  357. testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]);
  358. testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]);
  359. testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]);
  360. testMotion('%_parens', ['%'], parens1.end, parens1.start);
  361. testMotion('%_squares', ['%'], squares1.end, squares1.start);
  362. testMotion('%_braces', ['%'], curlys1.end, curlys1.start);
  363. testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start);
  364. testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start);
  365. testVim('%_seek_skip', function(cm, vim, helpers) {
  366. cm.setCursor(0,0);
  367. helpers.doKeys(['%']);
  368. helpers.assertCursorAt(0,9);
  369. }, {value:'01234"("()'});
  370. testVim('%_skip_string', function(cm, vim, helpers) {
  371. cm.setCursor(0,0);
  372. helpers.doKeys(['%']);
  373. helpers.assertCursorAt(0,4);
  374. cm.setCursor(0,2);
  375. helpers.doKeys(['%']);
  376. helpers.assertCursorAt(0,0);
  377. }, {value:'(")")'});
  378. (')')
  379. testVim('%_skip_comment', function(cm, vim, helpers) {
  380. cm.setCursor(0,0);
  381. helpers.doKeys(['%']);
  382. helpers.assertCursorAt(0,6);
  383. cm.setCursor(0,3);
  384. helpers.doKeys(['%']);
  385. helpers.assertCursorAt(0,0);
  386. }, {value:'(/*)*/)'});
  387. // Make sure that moving down after going to the end of a line always leaves you
  388. // at the end of a line, but preserves the offset in other cases
  389. testVim('Changing lines after Eol operation', function(cm, vim, helpers) {
  390. cm.setCursor(0,0);
  391. helpers.doKeys(['$']);
  392. helpers.doKeys(['j']);
  393. // After moving to Eol and then down, we should be at Eol of line 2
  394. helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 });
  395. helpers.doKeys(['j']);
  396. // After moving down, we should be at Eol of line 3
  397. helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 });
  398. helpers.doKeys(['h']);
  399. helpers.doKeys(['j']);
  400. // After moving back one space and then down, since line 4 is shorter than line 2, we should
  401. // be at Eol of line 2 - 1
  402. helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 });
  403. helpers.doKeys(['j']);
  404. helpers.doKeys(['j']);
  405. // After moving down again, since line 3 has enough characters, we should be back to the
  406. // same place we were at on line 1
  407. helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 });
  408. });
  409. //making sure gj and gk recover from clipping
  410. testVim('gj_gk_clipping', function(cm,vim,helpers){
  411. cm.setCursor(0, 1);
  412. helpers.doKeys('g','j','g','j');
  413. helpers.assertCursorAt(2, 1);
  414. helpers.doKeys('g','k','g','k');
  415. helpers.assertCursorAt(0, 1);
  416. },{value: 'line 1\n\nline 2'});
  417. //testing a mix of j/k and gj/gk
  418. testVim('j_k_and_gj_gk', function(cm,vim,helpers){
  419. cm.setSize(120);
  420. cm.setCursor(0, 0);
  421. //go to the last character on the first line
  422. helpers.doKeys('$');
  423. //move up/down on the column within the wrapped line
  424. //side-effect: cursor is not locked to eol anymore
  425. helpers.doKeys('g','k');
  426. var cur=cm.getCursor();
  427. eq(cur.line,0);
  428. is((cur.ch<176),'gk didn\'t move cursor back (1)');
  429. helpers.doKeys('g','j');
  430. helpers.assertCursorAt(0, 176);
  431. //should move to character 177 on line 2 (j/k preserve character index within line)
  432. helpers.doKeys('j');
  433. //due to different line wrapping, the cursor can be on a different screen-x now
  434. //gj and gk preserve screen-x on movement, much like moveV
  435. helpers.doKeys('3','g','k');
  436. cur=cm.getCursor();
  437. eq(cur.line,1);
  438. is((cur.ch<176),'gk didn\'t move cursor back (2)');
  439. helpers.doKeys('g','j','2','g','j');
  440. //should return to the same character-index
  441. helpers.doKeys('k');
  442. helpers.assertCursorAt(0, 176);
  443. },{ 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.'});
  444. testVim('gj_gk', function(cm, vim, helpers) {
  445. if (phantom) return;
  446. cm.setSize(120);
  447. // Test top of document edge case.
  448. cm.setCursor(0, 4);
  449. helpers.doKeys('g', 'j');
  450. helpers.doKeys('10', 'g', 'k');
  451. helpers.assertCursorAt(0, 4);
  452. // Test moving down preserves column position.
  453. helpers.doKeys('g', 'j');
  454. var pos1 = cm.getCursor();
  455. var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4};
  456. helpers.doKeys('g', 'j');
  457. helpers.assertCursorAt(expectedPos2);
  458. // Move to the last character
  459. cm.setCursor(0, 0);
  460. // Move left to reset HSPos
  461. helpers.doKeys('h');
  462. // Test bottom of document edge case.
  463. helpers.doKeys('100', 'g', 'j');
  464. var endingPos = cm.getCursor();
  465. is(endingPos != 0, 'gj should not be on wrapped line 0');
  466. var topLeftCharCoords = cm.charCoords(makeCursor(0, 0));
  467. var endingCharCoords = cm.charCoords(endingPos);
  468. is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0');
  469. },{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' });
  470. testVim('}', function(cm, vim, helpers) {
  471. cm.setCursor(0, 0);
  472. helpers.doKeys('}');
  473. helpers.assertCursorAt(1, 0);
  474. cm.setCursor(0, 0);
  475. helpers.doKeys('2', '}');
  476. helpers.assertCursorAt(4, 0);
  477. cm.setCursor(0, 0);
  478. helpers.doKeys('6', '}');
  479. helpers.assertCursorAt(5, 0);
  480. }, { value: 'a\n\nb\nc\n\nd' });
  481. testVim('{', function(cm, vim, helpers) {
  482. cm.setCursor(5, 0);
  483. helpers.doKeys('{');
  484. helpers.assertCursorAt(4, 0);
  485. cm.setCursor(5, 0);
  486. helpers.doKeys('2', '{');
  487. helpers.assertCursorAt(1, 0);
  488. cm.setCursor(5, 0);
  489. helpers.doKeys('6', '{');
  490. helpers.assertCursorAt(0, 0);
  491. }, { value: 'a\n\nb\nc\n\nd' });
  492. // Operator tests
  493. testVim('dl', function(cm, vim, helpers) {
  494. var curStart = makeCursor(0, 0);
  495. cm.setCursor(curStart);
  496. helpers.doKeys('d', 'l');
  497. eq('word1 ', cm.getValue());
  498. var register = helpers.getRegisterController().getRegister();
  499. eq(' ', register.toString());
  500. is(!register.linewise);
  501. eqPos(curStart, cm.getCursor());
  502. }, { value: ' word1 ' });
  503. testVim('dl_eol', function(cm, vim, helpers) {
  504. cm.setCursor(0, 6);
  505. helpers.doKeys('d', 'l');
  506. eq(' word1', cm.getValue());
  507. var register = helpers.getRegisterController().getRegister();
  508. eq(' ', register.toString());
  509. is(!register.linewise);
  510. helpers.assertCursorAt(0, 6);
  511. }, { value: ' word1 ' });
  512. testVim('dl_repeat', function(cm, vim, helpers) {
  513. var curStart = makeCursor(0, 0);
  514. cm.setCursor(curStart);
  515. helpers.doKeys('2', 'd', 'l');
  516. eq('ord1 ', cm.getValue());
  517. var register = helpers.getRegisterController().getRegister();
  518. eq(' w', register.toString());
  519. is(!register.linewise);
  520. eqPos(curStart, cm.getCursor());
  521. }, { value: ' word1 ' });
  522. testVim('dh', function(cm, vim, helpers) {
  523. var curStart = makeCursor(0, 3);
  524. cm.setCursor(curStart);
  525. helpers.doKeys('d', 'h');
  526. eq(' wrd1 ', cm.getValue());
  527. var register = helpers.getRegisterController().getRegister();
  528. eq('o', register.toString());
  529. is(!register.linewise);
  530. eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor());
  531. }, { value: ' word1 ' });
  532. testVim('dj', function(cm, vim, helpers) {
  533. var curStart = makeCursor(0, 3);
  534. cm.setCursor(curStart);
  535. helpers.doKeys('d', 'j');
  536. eq(' word3', cm.getValue());
  537. var register = helpers.getRegisterController().getRegister();
  538. eq(' word1\nword2\n', register.toString());
  539. is(register.linewise);
  540. helpers.assertCursorAt(0, 1);
  541. }, { value: ' word1\nword2\n word3' });
  542. testVim('dj_end_of_document', function(cm, vim, helpers) {
  543. var curStart = makeCursor(0, 3);
  544. cm.setCursor(curStart);
  545. helpers.doKeys('d', 'j');
  546. eq(' word1 ', cm.getValue());
  547. var register = helpers.getRegisterController().getRegister();
  548. eq('', register.toString());
  549. is(!register.linewise);
  550. helpers.assertCursorAt(0, 3);
  551. }, { value: ' word1 ' });
  552. testVim('dk', function(cm, vim, helpers) {
  553. var curStart = makeCursor(1, 3);
  554. cm.setCursor(curStart);
  555. helpers.doKeys('d', 'k');
  556. eq(' word3', cm.getValue());
  557. var register = helpers.getRegisterController().getRegister();
  558. eq(' word1\nword2\n', register.toString());
  559. is(register.linewise);
  560. helpers.assertCursorAt(0, 1);
  561. }, { value: ' word1\nword2\n word3' });
  562. testVim('dk_start_of_document', function(cm, vim, helpers) {
  563. var curStart = makeCursor(0, 3);
  564. cm.setCursor(curStart);
  565. helpers.doKeys('d', 'k');
  566. eq(' word1 ', cm.getValue());
  567. var register = helpers.getRegisterController().getRegister();
  568. eq('', register.toString());
  569. is(!register.linewise);
  570. helpers.assertCursorAt(0, 3);
  571. }, { value: ' word1 ' });
  572. testVim('dw_space', function(cm, vim, helpers) {
  573. var curStart = makeCursor(0, 0);
  574. cm.setCursor(curStart);
  575. helpers.doKeys('d', 'w');
  576. eq('word1 ', cm.getValue());
  577. var register = helpers.getRegisterController().getRegister();
  578. eq(' ', register.toString());
  579. is(!register.linewise);
  580. eqPos(curStart, cm.getCursor());
  581. }, { value: ' word1 ' });
  582. testVim('dw_word', function(cm, vim, helpers) {
  583. var curStart = makeCursor(0, 1);
  584. cm.setCursor(curStart);
  585. helpers.doKeys('d', 'w');
  586. eq(' word2', cm.getValue());
  587. var register = helpers.getRegisterController().getRegister();
  588. eq('word1 ', register.toString());
  589. is(!register.linewise);
  590. eqPos(curStart, cm.getCursor());
  591. }, { value: ' word1 word2' });
  592. testVim('dw_only_word', function(cm, vim, helpers) {
  593. // Test that if there is only 1 word left, dw deletes till the end of the
  594. // line.
  595. cm.setCursor(0, 1);
  596. helpers.doKeys('d', 'w');
  597. eq(' ', cm.getValue());
  598. var register = helpers.getRegisterController().getRegister();
  599. eq('word1 ', register.toString());
  600. is(!register.linewise);
  601. helpers.assertCursorAt(0, 1);
  602. }, { value: ' word1 ' });
  603. testVim('dw_eol', function(cm, vim, helpers) {
  604. // Assert that dw does not delete the newline if last word to delete is at end
  605. // of line.
  606. cm.setCursor(0, 1);
  607. helpers.doKeys('d', 'w');
  608. eq(' \nword2', cm.getValue());
  609. var register = helpers.getRegisterController().getRegister();
  610. eq('word1', register.toString());
  611. is(!register.linewise);
  612. helpers.assertCursorAt(0, 1);
  613. }, { value: ' word1\nword2' });
  614. testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {
  615. // Assert that dw does not delete the newline if last word to delete is at end
  616. // of line and it is followed by multiple newlines.
  617. cm.setCursor(0, 1);
  618. helpers.doKeys('d', 'w');
  619. eq(' \n\nword2', cm.getValue());
  620. var register = helpers.getRegisterController().getRegister();
  621. eq('word1', register.toString());
  622. is(!register.linewise);
  623. helpers.assertCursorAt(0, 1);
  624. }, { value: ' word1\n\nword2' });
  625. testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) {
  626. cm.setCursor(0, 0);
  627. helpers.doKeys('d', 'w');
  628. eq(' \nword', cm.getValue());
  629. }, { value: '\n \nword' });
  630. testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) {
  631. cm.setCursor(0, 0);
  632. helpers.doKeys('d', 'w');
  633. eq('word', cm.getValue());
  634. }, { value: '\nword' });
  635. testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) {
  636. cm.setCursor(0, 0);
  637. helpers.doKeys('d', 'w');
  638. eq('\n', cm.getValue());
  639. }, { value: '\n\n' });
  640. testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) {
  641. cm.setCursor(0, 0);
  642. helpers.doKeys('d', 'w');
  643. eq('\n \n', cm.getValue());
  644. }, { value: ' \n \n' });
  645. testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) {
  646. cm.setCursor(0, 0);
  647. helpers.doKeys('d', 'w');
  648. eq('\n\n', cm.getValue());
  649. }, { value: ' \n\n' });
  650. testVim('dw_word_whitespace_word', function(cm, vim, helpers) {
  651. cm.setCursor(0, 0);
  652. helpers.doKeys('d', 'w');
  653. eq('\n \nword2', cm.getValue());
  654. }, { value: 'word1\n \nword2'})
  655. testVim('dw_end_of_document', function(cm, vim, helpers) {
  656. cm.setCursor(1, 2);
  657. helpers.doKeys('d', 'w');
  658. eq('\nab', cm.getValue());
  659. }, { value: '\nabc' });
  660. testVim('dw_repeat', function(cm, vim, helpers) {
  661. // Assert that dw does delete newline if it should go to the next line, and
  662. // that repeat works properly.
  663. cm.setCursor(0, 1);
  664. helpers.doKeys('d', '2', 'w');
  665. eq(' ', cm.getValue());
  666. var register = helpers.getRegisterController().getRegister();
  667. eq('word1\nword2', register.toString());
  668. is(!register.linewise);
  669. helpers.assertCursorAt(0, 1);
  670. }, { value: ' word1\nword2' });
  671. testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) {
  672. cm.setCursor(0, 0);
  673. helpers.doKeys('d', 'e');
  674. eq('\n\n', cm.getValue());
  675. }, { value: 'word\n\n' });
  676. testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) {
  677. cm.setCursor(0, 3);
  678. helpers.doKeys('d', 'e');
  679. eq('wor', cm.getValue());
  680. }, { value: 'word\n\n\n' });
  681. testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) {
  682. cm.setCursor(0, 0);
  683. helpers.doKeys('d', 'e');
  684. eq('', cm.getValue());
  685. }, { value: ' \n\n\n' });
  686. testVim('de_end_of_document', function(cm, vim, helpers) {
  687. cm.setCursor(1, 2);
  688. helpers.doKeys('d', 'e');
  689. eq('\nab', cm.getValue());
  690. }, { value: '\nabc' });
  691. testVim('db_empty_lines', function(cm, vim, helpers) {
  692. cm.setCursor(2, 0);
  693. helpers.doKeys('d', 'b');
  694. eq('\n\n', cm.getValue());
  695. }, { value: '\n\n\n' });
  696. testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) {
  697. cm.setCursor(2, 0);
  698. helpers.doKeys('d', 'b');
  699. eq('\nword', cm.getValue());
  700. }, { value: '\n\nword' });
  701. testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) {
  702. cm.setCursor(2, 3);
  703. helpers.doKeys('d', 'b');
  704. eq('\n\nd', cm.getValue());
  705. }, { value: '\n\nword' });
  706. testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) {
  707. cm.setCursor(2, 0);
  708. helpers.doKeys('d', 'b');
  709. eq('', cm.getValue());
  710. }, { value: '\n \n' });
  711. testVim('db_start_of_document', function(cm, vim, helpers) {
  712. cm.setCursor(0, 0);
  713. helpers.doKeys('d', 'b');
  714. eq('abc\n', cm.getValue());
  715. }, { value: 'abc\n' });
  716. testVim('dge_empty_lines', function(cm, vim, helpers) {
  717. cm.setCursor(1, 0);
  718. helpers.doKeys('d', 'g', 'e');
  719. // Note: In real VIM the result should be '', but it's not quite consistent,
  720. // since 2 newlines are deleted. But in the similar case of word\n\n, only
  721. // 1 newline is deleted. We'll diverge from VIM's behavior since it's much
  722. // easier this way.
  723. eq('\n', cm.getValue());
  724. }, { value: '\n\n' });
  725. testVim('dge_word_and_empty_lines', function(cm, vim, helpers) {
  726. cm.setCursor(1, 0);
  727. helpers.doKeys('d', 'g', 'e');
  728. eq('wor\n', cm.getValue());
  729. }, { value: 'word\n\n'});
  730. testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) {
  731. cm.setCursor(2, 0);
  732. helpers.doKeys('d', 'g', 'e');
  733. eq('', cm.getValue());
  734. }, { value: '\n \n' });
  735. testVim('dge_start_of_document', function(cm, vim, helpers) {
  736. cm.setCursor(0, 0);
  737. helpers.doKeys('d', 'g', 'e');
  738. eq('bc\n', cm.getValue());
  739. }, { value: 'abc\n' });
  740. testVim('d_inclusive', function(cm, vim, helpers) {
  741. // Assert that when inclusive is set, the character the cursor is on gets
  742. // deleted too.
  743. var curStart = makeCursor(0, 1);
  744. cm.setCursor(curStart);
  745. helpers.doKeys('d', 'e');
  746. eq(' ', cm.getValue());
  747. var register = helpers.getRegisterController().getRegister();
  748. eq('word1', register.toString());
  749. is(!register.linewise);
  750. eqPos(curStart, cm.getCursor());
  751. }, { value: ' word1 ' });
  752. testVim('d_reverse', function(cm, vim, helpers) {
  753. // Test that deleting in reverse works.
  754. cm.setCursor(1, 0);
  755. helpers.doKeys('d', 'b');
  756. eq(' word2 ', cm.getValue());
  757. var register = helpers.getRegisterController().getRegister();
  758. eq('word1\n', register.toString());
  759. is(!register.linewise);
  760. helpers.assertCursorAt(0, 1);
  761. }, { value: ' word1\nword2 ' });
  762. testVim('dd', function(cm, vim, helpers) {
  763. cm.setCursor(0, 3);
  764. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  765. { line: 1, ch: 0 });
  766. var expectedLineCount = cm.lineCount() - 1;
  767. helpers.doKeys('d', 'd');
  768. eq(expectedLineCount, cm.lineCount());
  769. var register = helpers.getRegisterController().getRegister();
  770. eq(expectedBuffer, register.toString());
  771. is(register.linewise);
  772. helpers.assertCursorAt(0, lines[1].textStart);
  773. });
  774. testVim('dd_prefix_repeat', function(cm, vim, helpers) {
  775. cm.setCursor(0, 3);
  776. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  777. { line: 2, ch: 0 });
  778. var expectedLineCount = cm.lineCount() - 2;
  779. helpers.doKeys('2', 'd', 'd');
  780. eq(expectedLineCount, cm.lineCount());
  781. var register = helpers.getRegisterController().getRegister();
  782. eq(expectedBuffer, register.toString());
  783. is(register.linewise);
  784. helpers.assertCursorAt(0, lines[2].textStart);
  785. });
  786. testVim('dd_motion_repeat', function(cm, vim, helpers) {
  787. cm.setCursor(0, 3);
  788. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  789. { line: 2, ch: 0 });
  790. var expectedLineCount = cm.lineCount() - 2;
  791. helpers.doKeys('d', '2', 'd');
  792. eq(expectedLineCount, cm.lineCount());
  793. var register = helpers.getRegisterController().getRegister();
  794. eq(expectedBuffer, register.toString());
  795. is(register.linewise);
  796. helpers.assertCursorAt(0, lines[2].textStart);
  797. });
  798. testVim('dd_multiply_repeat', function(cm, vim, helpers) {
  799. cm.setCursor(0, 3);
  800. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  801. { line: 6, ch: 0 });
  802. var expectedLineCount = cm.lineCount() - 6;
  803. helpers.doKeys('2', 'd', '3', 'd');
  804. eq(expectedLineCount, cm.lineCount());
  805. var register = helpers.getRegisterController().getRegister();
  806. eq(expectedBuffer, register.toString());
  807. is(register.linewise);
  808. helpers.assertCursorAt(0, lines[6].textStart);
  809. });
  810. testVim('dd_lastline', function(cm, vim, helpers) {
  811. cm.setCursor(cm.lineCount(), 0);
  812. var expectedLineCount = cm.lineCount() - 1;
  813. helpers.doKeys('d', 'd');
  814. eq(expectedLineCount, cm.lineCount());
  815. helpers.assertCursorAt(cm.lineCount() - 1, 0);
  816. });
  817. // Yank commands should behave the exact same as d commands, expect that nothing
  818. // gets deleted.
  819. testVim('yw_repeat', function(cm, vim, helpers) {
  820. // Assert that yw does yank newline if it should go to the next line, and
  821. // that repeat works properly.
  822. var curStart = makeCursor(0, 1);
  823. cm.setCursor(curStart);
  824. helpers.doKeys('y', '2', 'w');
  825. eq(' word1\nword2', cm.getValue());
  826. var register = helpers.getRegisterController().getRegister();
  827. eq('word1\nword2', register.toString());
  828. is(!register.linewise);
  829. eqPos(curStart, cm.getCursor());
  830. }, { value: ' word1\nword2' });
  831. testVim('yy_multiply_repeat', function(cm, vim, helpers) {
  832. var curStart = makeCursor(0, 3);
  833. cm.setCursor(curStart);
  834. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  835. { line: 6, ch: 0 });
  836. var expectedLineCount = cm.lineCount();
  837. helpers.doKeys('2', 'y', '3', 'y');
  838. eq(expectedLineCount, cm.lineCount());
  839. var register = helpers.getRegisterController().getRegister();
  840. eq(expectedBuffer, register.toString());
  841. is(register.linewise);
  842. eqPos(curStart, cm.getCursor());
  843. });
  844. // Change commands behave like d commands except that it also enters insert
  845. // mode. In addition, when the change is linewise, an additional newline is
  846. // inserted so that insert mode starts on that line.
  847. testVim('cw', function(cm, vim, helpers) {
  848. cm.setCursor(0, 0);
  849. helpers.doKeys('c', '2', 'w');
  850. eq(' word3', cm.getValue());
  851. helpers.assertCursorAt(0, 0);
  852. }, { value: 'word1 word2 word3'});
  853. testVim('cw_repeat', function(cm, vim, helpers) {
  854. // Assert that cw does delete newline if it should go to the next line, and
  855. // that repeat works properly.
  856. var curStart = makeCursor(0, 1);
  857. cm.setCursor(curStart);
  858. helpers.doKeys('c', '2', 'w');
  859. eq(' ', cm.getValue());
  860. var register = helpers.getRegisterController().getRegister();
  861. eq('word1\nword2', register.toString());
  862. is(!register.linewise);
  863. eqPos(curStart, cm.getCursor());
  864. eq('vim-insert', cm.getOption('keyMap'));
  865. }, { value: ' word1\nword2' });
  866. testVim('cc_multiply_repeat', function(cm, vim, helpers) {
  867. cm.setCursor(0, 3);
  868. var expectedBuffer = cm.getRange({ line: 0, ch: 0 },
  869. { line: 6, ch: 0 });
  870. var expectedLineCount = cm.lineCount() - 5;
  871. helpers.doKeys('2', 'c', '3', 'c');
  872. eq(expectedLineCount, cm.lineCount());
  873. var register = helpers.getRegisterController().getRegister();
  874. eq(expectedBuffer, register.toString());
  875. is(register.linewise);
  876. eq('vim-insert', cm.getOption('keyMap'));
  877. });
  878. testVim('cc_append', function(cm, vim, helpers) {
  879. var expectedLineCount = cm.lineCount();
  880. cm.setCursor(cm.lastLine(), 0);
  881. helpers.doKeys('c', 'c');
  882. eq(expectedLineCount, cm.lineCount());
  883. });
  884. testVim('c_visual_block', function(cm, vim, helpers) {
  885. cm.setCursor(0, 1);
  886. helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'l', 'c');
  887. var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' ');
  888. replacement.pop();
  889. cm.replaceSelections(replacement);
  890. eq('1hello\n5hello\nahellofg', cm.getValue());
  891. cm.setCursor(2, 3);
  892. helpers.doKeys('<C-v>', '2', 'k', 'h', 'C');
  893. replacement = new Array(cm.listSelections().length+1).join('world ').split(' ');
  894. replacement.pop();
  895. cm.replaceSelections(replacement);
  896. eq('1hworld\n5hworld\nahworld', cm.getValue());
  897. }, {value: '1234\n5678\nabcdefg'});
  898. testVim('c_visual_block_replay', function(cm, vim, helpers) {
  899. cm.setCursor(0, 1);
  900. helpers.doKeys('<C-v>', '2', 'j', 'l', 'c');
  901. var replacement = new Array(cm.listSelections().length+1).join('fo ').split(' ');
  902. replacement.pop();
  903. cm.replaceSelections(replacement);
  904. eq('1fo4\n5fo8\nafodefg', cm.getValue());
  905. helpers.doInsertModeKeys('Esc');
  906. cm.setCursor(0, 0);
  907. helpers.doKeys('.');
  908. eq('foo4\nfoo8\nfoodefg', cm.getValue());
  909. }, {value: '1234\n5678\nabcdefg'});
  910. // Swapcase commands edit in place and do not modify registers.
  911. testVim('g~w_repeat', function(cm, vim, helpers) {
  912. // Assert that dw does delete newline if it should go to the next line, and
  913. // that repeat works properly.
  914. var curStart = makeCursor(0, 1);
  915. cm.setCursor(curStart);
  916. helpers.doKeys('g', '~', '2', 'w');
  917. eq(' WORD1\nWORD2', cm.getValue());
  918. var register = helpers.getRegisterController().getRegister();
  919. eq('', register.toString());
  920. is(!register.linewise);
  921. eqPos(curStart, cm.getCursor());
  922. }, { value: ' word1\nword2' });
  923. testVim('g~g~', function(cm, vim, helpers) {
  924. var curStart = makeCursor(0, 3);
  925. cm.setCursor(curStart);
  926. var expectedLineCount = cm.lineCount();
  927. var expectedValue = cm.getValue().toUpperCase();
  928. helpers.doKeys('2', 'g', '~', '3', 'g', '~');
  929. eq(expectedValue, cm.getValue());
  930. var register = helpers.getRegisterController().getRegister();
  931. eq('', register.toString());
  932. is(!register.linewise);
  933. eqPos({line: curStart.line, ch:0}, cm.getCursor());
  934. }, { value: ' word1\nword2\nword3\nword4\nword5\nword6' });
  935. testVim('visual_block_~', function(cm, vim, helpers) {
  936. cm.setCursor(1, 1);
  937. helpers.doKeys('<C-v>', 'l', 'l', 'j', '~');
  938. helpers.assertCursorAt(1, 1);
  939. eq('hello\nwoRLd\naBCDe', cm.getValue());
  940. cm.setCursor(2, 0);
  941. helpers.doKeys('v', 'l', 'l', '~');
  942. helpers.assertCursorAt(2, 0);
  943. eq('hello\nwoRLd\nAbcDe', cm.getValue());
  944. },{value: 'hello\nwOrld\nabcde' });
  945. testVim('._swapCase_visualBlock', function(cm, vim, helpers) {
  946. helpers.doKeys('<C-v>', 'j', 'j', 'l', '~');
  947. cm.setCursor(0, 3);
  948. helpers.doKeys('.');
  949. eq('HelLO\nWorLd\nAbcdE', cm.getValue());
  950. },{value: 'hEllo\nwOrlD\naBcDe' });
  951. testVim('._delete_visualBlock', function(cm, vim, helpers) {
  952. helpers.doKeys('<C-v>', 'j', 'x');
  953. eq('ive\ne\nsome\nsugar', cm.getValue());
  954. helpers.doKeys('.');
  955. eq('ve\n\nsome\nsugar', cm.getValue());
  956. helpers.doKeys('j', 'j', '.');
  957. eq('ve\n\nome\nugar', cm.getValue());
  958. helpers.doKeys('u', '<C-r>', '.');
  959. eq('ve\n\nme\ngar', cm.getValue());
  960. },{value: 'give\nme\nsome\nsugar' });
  961. testVim('>{motion}', function(cm, vim, helpers) {
  962. cm.setCursor(1, 3);
  963. var expectedLineCount = cm.lineCount();
  964. var expectedValue = ' word1\n word2\nword3 ';
  965. helpers.doKeys('>', 'k');
  966. eq(expectedValue, cm.getValue());
  967. var register = helpers.getRegisterController().getRegister();
  968. eq('', register.toString());
  969. is(!register.linewise);
  970. helpers.assertCursorAt(0, 3);
  971. }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
  972. testVim('>>', function(cm, vim, helpers) {
  973. cm.setCursor(0, 3);
  974. var expectedLineCount = cm.lineCount();
  975. var expectedValue = ' word1\n word2\nword3 ';
  976. helpers.doKeys('2', '>', '>');
  977. eq(expectedValue, cm.getValue());
  978. var register = helpers.getRegisterController().getRegister();
  979. eq('', register.toString());
  980. is(!register.linewise);
  981. helpers.assertCursorAt(0, 3);
  982. }, { value: ' word1\nword2\nword3 ', indentUnit: 2 });
  983. testVim('<{motion}', function(cm, vim, helpers) {
  984. cm.setCursor(1, 3);
  985. var expectedLineCount = cm.lineCount();
  986. var expectedValue = ' word1\nword2\nword3 ';
  987. helpers.doKeys('<', 'k');
  988. eq(expectedValue, cm.getValue());
  989. var register = helpers.getRegisterController().getRegister();
  990. eq('', register.toString());
  991. is(!register.linewise);
  992. helpers.assertCursorAt(0, 1);
  993. }, { value: ' word1\n word2\nword3 ', indentUnit: 2 });
  994. testVim('<<', function(cm, vim, helpers) {
  995. cm.setCursor(0, 3);
  996. var expectedLineCount = cm.lineCount();
  997. var expectedValue = ' word1\nword2\nword3 ';
  998. helpers.doKeys('2', '<', '<');
  999. eq(expectedValue, cm.getValue());
  1000. var register = helpers.getRegisterController().getRegister();
  1001. eq('', register.toString());
  1002. is(!register.linewise);
  1003. helpers.assertCursorAt(0, 1);
  1004. }, { value: ' word1\n word2\nword3 ', indentUnit: 2 });
  1005. // Edit tests
  1006. function testEdit(name, before, pos, edit, after) {
  1007. return testVim(name, function(cm, vim, helpers) {
  1008. var ch = before.search(pos)
  1009. var line = before.substring(0, ch).split('\n').length - 1;
  1010. if (line) {
  1011. ch = before.substring(0, ch).split('\n').pop().length;
  1012. }
  1013. cm.setCursor(line, ch);
  1014. helpers.doKeys.apply(this, edit.split(''));
  1015. eq(after, cm.getValue());
  1016. }, {value: before});
  1017. }
  1018. // These Delete tests effectively cover word-wise Change, Visual & Yank.
  1019. // Tabs are used as differentiated whitespace to catch edge cases.
  1020. // Normal word:
  1021. testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz');
  1022. testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz');
  1023. testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz');
  1024. testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz');
  1025. testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz');
  1026. testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz');
  1027. testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz');
  1028. testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz');
  1029. testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz');
  1030. testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz');
  1031. testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t');
  1032. testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo');
  1033. testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.');
  1034. testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.');
  1035. // Big word:
  1036. testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz');
  1037. testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz');
  1038. testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz');
  1039. testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz');
  1040. testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz');
  1041. testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz');
  1042. testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz');
  1043. testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz');
  1044. testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz');
  1045. testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz');
  1046. testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t');
  1047. testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo');
  1048. testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t');
  1049. testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo');
  1050. // Deleting text objects
  1051. // Open and close on same line
  1052. testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz');
  1053. testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz');
  1054. testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz');
  1055. testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz');
  1056. testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz');
  1057. testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz');
  1058. testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz');
  1059. testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz');
  1060. testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz');
  1061. testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz');
  1062. testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz');
  1063. testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz');
  1064. testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz');
  1065. // delete around and inner b.
  1066. testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )');
  1067. // delete around and inner B.
  1068. testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }');
  1069. testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }');
  1070. testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }');
  1071. testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz');
  1072. testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz');
  1073. testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz');
  1074. testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz');
  1075. testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0});
  1076. // Open and close on different lines, equally indented
  1077. testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b');
  1078. testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b');
  1079. testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab');
  1080. testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab');
  1081. testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab');
  1082. // open and close on diff lines, open indented less than close
  1083. testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b');
  1084. testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b');
  1085. testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab');
  1086. testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab');
  1087. // open and close on diff lines, open indented more than close
  1088. testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b');
  1089. testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b');
  1090. testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb');
  1091. testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb');
  1092. // Operator-motion tests
  1093. testVim('D', function(cm, vim, helpers) {
  1094. cm.setCursor(0, 3);
  1095. helpers.doKeys('D');
  1096. eq(' wo\nword2\n word3', cm.getValue());
  1097. var register = helpers.getRegisterController().getRegister();
  1098. eq('rd1', register.toString());
  1099. is(!register.linewise);
  1100. helpers.assertCursorAt(0, 3);
  1101. }, { value: ' word1\nword2\n word3' });
  1102. testVim('C', function(cm, vim, helpers) {
  1103. var curStart = makeCursor(0, 3);
  1104. cm.setCursor(curStart);
  1105. helpers.doKeys('C');
  1106. eq(' wo\nword2\n word3', cm.getValue());
  1107. var register = helpers.getRegisterController().getRegister();
  1108. eq('rd1', register.toString());
  1109. is(!register.linewise);
  1110. eqPos(curStart, cm.getCursor());
  1111. eq('vim-insert', cm.getOption('keyMap'));
  1112. }, { value: ' word1\nword2\n word3' });
  1113. testVim('Y', function(cm, vim, helpers) {
  1114. var curStart = makeCursor(0, 3);
  1115. cm.setCursor(curStart);
  1116. helpers.doKeys('Y');
  1117. eq(' word1\nword2\n word3', cm.getValue());
  1118. var register = helpers.getRegisterController().getRegister();
  1119. eq('rd1', register.toString());
  1120. is(!register.linewise);
  1121. helpers.assertCursorAt(0, 3);
  1122. }, { value: ' word1\nword2\n word3' });
  1123. testVim('~', function(cm, vim, helpers) {
  1124. helpers.doKeys('3', '~');
  1125. eq('ABCdefg', cm.getValue());
  1126. helpers.assertCursorAt(0, 3);
  1127. }, { value: 'abcdefg' });
  1128. // Action tests
  1129. testVim('ctrl-a', function(cm, vim, helpers) {
  1130. cm.setCursor(0, 0);
  1131. helpers.doKeys('<C-a>');
  1132. eq('-9', cm.getValue());
  1133. helpers.assertCursorAt(0, 1);
  1134. helpers.doKeys('2','<C-a>');
  1135. eq('-7', cm.getValue());
  1136. }, {value: '-10'});
  1137. testVim('ctrl-x', function(cm, vim, helpers) {
  1138. cm.setCursor(0, 0);
  1139. helpers.doKeys('<C-x>');
  1140. eq('-1', cm.getValue());
  1141. helpers.assertCursorAt(0, 1);
  1142. helpers.doKeys('2','<C-x>');
  1143. eq('-3', cm.getValue());
  1144. }, {value: '0'});
  1145. testVim('<C-x>/<C-a> search forward', function(cm, vim, helpers) {
  1146. forEach(['<C-x>', '<C-a>'], function(key) {
  1147. cm.setCursor(0, 0);
  1148. helpers.doKeys(key);
  1149. helpers.assertCursorAt(0, 5);
  1150. helpers.doKeys('l');
  1151. helpers.doKeys(key);
  1152. helpers.assertCursorAt(0, 10);
  1153. cm.setCursor(0, 11);
  1154. helpers.doKeys(key);
  1155. helpers.assertCursorAt(0, 11);
  1156. });
  1157. }, {value: '__jmp1 jmp2 jmp'});
  1158. testVim('a', function(cm, vim, helpers) {
  1159. cm.setCursor(0, 1);
  1160. helpers.doKeys('a');
  1161. helpers.assertCursorAt(0, 2);
  1162. eq('vim-insert', cm.getOption('keyMap'));
  1163. });
  1164. testVim('a_eol', function(cm, vim, helpers) {
  1165. cm.setCursor(0, lines[0].length - 1);
  1166. helpers.doKeys('a');
  1167. helpers.assertCursorAt(0, lines[0].length);
  1168. eq('vim-insert', cm.getOption('keyMap'));
  1169. });
  1170. testVim('a_endOfSelectedArea', function(cm, vim, helpers) {
  1171. cm.setCursor(0, 0);
  1172. helpers.doKeys('v', 'j', 'l');
  1173. helpers.doKeys('A');
  1174. helpers.assertCursorAt(1, 2);
  1175. eq('vim-insert', cm.getOption('keyMap'));
  1176. }, {value: 'foo\nbar'});
  1177. testVim('i', function(cm, vim, helpers) {
  1178. cm.setCursor(0, 1);
  1179. helpers.doKeys('i');
  1180. helpers.assertCursorAt(0, 1);
  1181. eq('vim-insert', cm.getOption('keyMap'));
  1182. });
  1183. testVim('i_repeat', function(cm, vim, helpers) {
  1184. helpers.doKeys('3', 'i');
  1185. cm.replaceRange('test', cm.getCursor());
  1186. helpers.doInsertModeKeys('Esc');
  1187. eq('testtesttest', cm.getValue());
  1188. helpers.assertCursorAt(0, 11);
  1189. }, { value: '' });
  1190. testVim('i_repeat_delete', function(cm, vim, helpers) {
  1191. cm.setCursor(0, 4);
  1192. helpers.doKeys('2', 'i');
  1193. cm.replaceRange('z', cm.getCursor());
  1194. helpers.doInsertModeKeys('Backspace', 'Backspace', 'Esc');
  1195. eq('abe', cm.getValue());
  1196. helpers.assertCursorAt(0, 1);
  1197. }, { value: 'abcde' });
  1198. testVim('A', function(cm, vim, helpers) {
  1199. helpers.doKeys('A');
  1200. helpers.assertCursorAt(0, lines[0].length);
  1201. eq('vim-insert', cm.getOption('keyMap'));
  1202. });
  1203. testVim('A_visual_block', function(cm, vim, helpers) {
  1204. cm.setCursor(0, 1);
  1205. helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'A');
  1206. var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' ');
  1207. replacement.pop();
  1208. cm.replaceSelections(replacement);
  1209. eq('testhello\nmehello\npleahellose', cm.getValue());
  1210. }, {value: 'test\nme\nplease'});
  1211. testVim('I', function(cm, vim, helpers) {
  1212. cm.setCursor(0, 4);
  1213. helpers.doKeys('I');
  1214. helpers.assertCursorAt(0, lines[0].textStart);
  1215. eq('vim-insert', cm.getOption('keyMap'));
  1216. });
  1217. testVim('I_repeat', function(cm, vim, helpers) {
  1218. cm.setCursor(0, 1);
  1219. helpers.doKeys('3', 'I');
  1220. cm.replaceRange('test', cm.getCursor());
  1221. helpers.doInsertModeKeys('Esc');
  1222. eq('testtesttestblah', cm.getValue());
  1223. helpers.assertCursorAt(0, 11);
  1224. }, { value: 'blah' });
  1225. testVim('I_visual_block', function(cm, vim, helpers) {
  1226. cm.setCursor(0, 0);
  1227. helpers.doKeys('<C-v>', '2', 'j', 'l', 'l', 'I');
  1228. var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' ');
  1229. replacement.pop();
  1230. cm.replaceSelections(replacement);
  1231. eq('hellotest\nhellome\nhelloplease', cm.getValue());
  1232. }, {value: 'test\nme\nplease'});
  1233. testVim('o', function(cm, vim, helpers) {
  1234. cm.setCursor(0, 4);
  1235. helpers.doKeys('o');
  1236. eq('word1\n\nword2', cm.getValue());
  1237. helpers.assertCursorAt(1, 0);
  1238. eq('vim-insert', cm.getOption('keyMap'));
  1239. }, { value: 'word1\nword2' });
  1240. testVim('o_repeat', function(cm, vim, helpers) {
  1241. cm.setCursor(0, 0);
  1242. helpers.doKeys('3', 'o');
  1243. cm.replaceRange('test', cm.getCursor());
  1244. helpers.doInsertModeKeys('Esc');
  1245. eq('\ntest\ntest\ntest', cm.getValue());
  1246. helpers.assertCursorAt(3, 3);
  1247. }, { value: '' });
  1248. testVim('O', function(cm, vim, helpers) {
  1249. cm.setCursor(0, 4);
  1250. helpers.doKeys('O');
  1251. eq('\nword1\nword2', cm.getValue());
  1252. helpers.assertCursorAt(0, 0);
  1253. eq('vim-insert', cm.getOption('keyMap'));
  1254. }, { value: 'word1\nword2' });
  1255. testVim('J', function(cm, vim, helpers) {
  1256. cm.setCursor(0, 4);
  1257. helpers.doKeys('J');
  1258. var expectedValue = 'word1 word2\nword3\n word4';
  1259. eq(expectedValue, cm.getValue());
  1260. helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1);
  1261. }, { value: 'word1 \n word2\nword3\n word4' });
  1262. testVim('J_repeat', function(cm, vim, helpers) {
  1263. cm.setCursor(0, 4);
  1264. helpers.doKeys('3', 'J');
  1265. var expectedValue = 'word1 word2 word3\n word4';
  1266. eq(expectedValue, cm.getValue());
  1267. helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1);
  1268. }, { value: 'word1 \n word2\nword3\n word4' });
  1269. testVim('p', function(cm, vim, helpers) {
  1270. cm.setCursor(0, 1);
  1271. helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
  1272. helpers.doKeys('p');
  1273. eq('__abc\ndef_', cm.getValue());
  1274. helpers.assertCursorAt(1, 2);
  1275. }, { value: '___' });
  1276. testVim('p_register', function(cm, vim, helpers) {
  1277. cm.setCursor(0, 1);
  1278. helpers.getRegisterController().getRegister('a').setText('abc\ndef', false);
  1279. helpers.doKeys('"', 'a', 'p');
  1280. eq('__abc\ndef_', cm.getValue());
  1281. helpers.assertCursorAt(1, 2);
  1282. }, { value: '___' });
  1283. testVim('p_wrong_register', function(cm, vim, helpers) {
  1284. cm.setCursor(0, 1);
  1285. helpers.getRegisterController().getRegister('a').setText('abc\ndef', false);
  1286. helpers.doKeys('p');
  1287. eq('___', cm.getValue());
  1288. helpers.assertCursorAt(0, 1);
  1289. }, { value: '___' });
  1290. testVim('p_line', function(cm, vim, helpers) {
  1291. cm.setCursor(0, 1);
  1292. helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);
  1293. helpers.doKeys('2', 'p');
  1294. eq('___\n a\nd\n a\nd', cm.getValue());
  1295. helpers.assertCursorAt(1, 2);
  1296. }, { value: '___' });
  1297. testVim('p_lastline', function(cm, vim, helpers) {
  1298. cm.setCursor(0, 1);
  1299. helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true);
  1300. helpers.doKeys('2', 'p');
  1301. eq('___\n a\nd\n a\nd', cm.getValue());
  1302. helpers.assertCursorAt(1, 2);
  1303. }, { value: '___' });
  1304. testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) {
  1305. helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true);
  1306. helpers.doKeys(']', 'p');
  1307. eq(' ___\n abc\n def', cm.getValue());
  1308. }, { value: ' ___' });
  1309. testVim(']p_first_indent_is_larger', function(cm, vim, helpers) {
  1310. helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true);
  1311. helpers.doKeys(']', 'p');
  1312. eq(' ___\n abc\ndef', cm.getValue());
  1313. }, { value: ' ___' });
  1314. testVim(']p_with_tab_indents', function(cm, vim, helpers) {
  1315. helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true);
  1316. helpers.doKeys(']', 'p');
  1317. eq('\t___\n\tabc\n\t\tdef', cm.getValue());
  1318. }, { value: '\t___', indentWithTabs: true});
  1319. testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) {
  1320. helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true);
  1321. helpers.doKeys(']', 'p');
  1322. eq('\t___\n\tabc\n\t\tdef', cm.getValue());
  1323. }, { value: '\t___', indentWithTabs: true, tabSize: 2 });
  1324. testVim('[p', function(cm, vim, helpers) {
  1325. helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true);
  1326. helpers.doKeys('[', 'p');
  1327. eq(' abc\n def\n ___', cm.getValue());
  1328. }, { value: ' ___' });
  1329. testVim('P', function(cm, vim, helpers) {
  1330. cm.setCursor(0, 1);
  1331. helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false);
  1332. helpers.doKeys('P');
  1333. eq('_abc\ndef__', cm.getValue());
  1334. helpers.assertCursorAt(1, 3);
  1335. }, { value: '___' });
  1336. testVim('P_line', function(cm, vim, helpers) {
  1337. cm.setCursor(0, 1);
  1338. helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true);
  1339. helpers.doKeys('2', 'P');
  1340. eq(' a\nd\n a\nd\n___', cm.getValue());
  1341. helpers.assertCursorAt(0, 2);
  1342. }, { value: '___' });
  1343. testVim('r', function(cm, vim, helpers) {
  1344. cm.setCursor(0, 1);
  1345. helpers.doKeys('3', 'r', 'u');
  1346. eq('wuuuet\nanother', cm.getValue(),'3r failed');
  1347. helpers.assertCursorAt(0, 3);
  1348. cm.setCursor(0, 4);
  1349. helpers.doKeys('v', 'j', 'h', 'r', '<Space>');
  1350. eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed');
  1351. }, { value: 'wordet\nanother' });
  1352. testVim('r_visual_block', function(cm, vim, helpers) {
  1353. cm.setCursor(2, 3);
  1354. helpers.doKeys('<C-v>', 'k', 'k', 'h', 'h', 'r', 'l');
  1355. eq('1lll\n5lll\nalllefg', cm.getValue());
  1356. helpers.doKeys('<C-v>', 'l', 'j', 'r', '<Space>');
  1357. eq('1 l\n5 l\nalllefg', cm.getValue());
  1358. cm.setCursor(2, 0);
  1359. helpers.doKeys('o');
  1360. helpers.doInsertModeKeys('Esc');
  1361. cm.replaceRange('\t\t', cm.getCursor());
  1362. helpers.doKeys('<C-v>', 'h', 'h', 'r', 'r');
  1363. eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue());
  1364. }, {value: '1234\n5678\nabcdefg'});
  1365. testVim('R', function(cm, vim, helpers) {
  1366. cm.setCursor(0, 1);
  1367. helpers.doKeys('R');
  1368. helpers.assertCursorAt(0, 1);
  1369. eq('vim-replace', cm.getOption('keyMap'));
  1370. is(cm.state.overwrite, 'Setting overwrite state failed');
  1371. });
  1372. testVim('mark', function(cm, vim, helpers) {
  1373. cm.setCursor(2, 2);
  1374. helpers.doKeys('m', 't');
  1375. cm.setCursor(0, 0);
  1376. helpers.doKeys('`', 't');
  1377. helpers.assertCursorAt(2, 2);
  1378. cm.setCursor(2, 0);
  1379. cm.replaceRange(' h', cm.getCursor());
  1380. cm.setCursor(0, 0);
  1381. helpers.doKeys('\'', 't');
  1382. helpers.assertCursorAt(2, 3);
  1383. });
  1384. testVim('jumpToMark_next', function(cm, vim, helpers) {
  1385. cm.setCursor(2, 2);
  1386. helpers.doKeys('m', 't');
  1387. cm.setCursor(0, 0);
  1388. helpers.doKeys(']', '`');
  1389. helpers.assertCursorAt(2, 2);
  1390. cm.setCursor(0, 0);
  1391. helpers.doKeys(']', '\'');
  1392. helpers.assertCursorAt(2, 0);
  1393. });
  1394. testVim('jumpToMark_next_repeat', function(cm, vim, helpers) {
  1395. cm.setCursor(2, 2);
  1396. helpers.doKeys('m', 'a');
  1397. cm.setCursor(3, 2);
  1398. helpers.doKeys('m', 'b');
  1399. cm.setCursor(4, 2);
  1400. helpers.doKeys('m', 'c');
  1401. cm.setCursor(0, 0);
  1402. helpers.doKeys('2', ']', '`');
  1403. helpers.assertCursorAt(3, 2);
  1404. cm.setCursor(0, 0);
  1405. helpers.doKeys('2', ']', '\'');
  1406. helpers.assertCursorAt(3, 1);
  1407. });
  1408. testVim('jumpToMark_next_sameline', function(cm, vim, helpers) {
  1409. cm.setCursor(2, 0);
  1410. helpers.doKeys('m', 'a');
  1411. cm.setCursor(2, 4);
  1412. helpers.doKeys('m', 'b');
  1413. cm.setCursor(2, 2);
  1414. helpers.doKeys(']', '`');
  1415. helpers.assertCursorAt(2, 4);
  1416. });
  1417. testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) {
  1418. cm.setCursor(2, 0);
  1419. helpers.doKeys('m', 'a');
  1420. cm.setCursor(4, 0);
  1421. helpers.doKeys(']', '`');
  1422. helpers.assertCursorAt(4, 0);
  1423. });
  1424. testVim('jumpToMark_next_nomark', function(cm, vim, helpers) {
  1425. cm.setCursor(2, 2);
  1426. helpers.doKeys(']', '`');
  1427. helpers.assertCursorAt(2, 2);
  1428. helpers.doKeys(']', '\'');
  1429. helpers.assertCursorAt(2, 0);
  1430. });
  1431. testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) {
  1432. cm.setCursor(2, 2);
  1433. helpers.doKeys('m', 'a');
  1434. cm.setCursor(3, 4);
  1435. helpers.doKeys('m', 'b');
  1436. cm.setCursor(2, 1);
  1437. helpers.doKeys(']', '\'');
  1438. helpers.assertCursorAt(3, 1);
  1439. });
  1440. testVim('jumpToMark_next_action', function(cm, vim, helpers) {
  1441. cm.setCursor(2, 2);
  1442. helpers.doKeys('m', 't');
  1443. cm.setCursor(0, 0);
  1444. helpers.doKeys('d', ']', '`');
  1445. helpers.assertCursorAt(0, 0);
  1446. var actual = cm.getLine(0);
  1447. var expected = 'pop pop 0 1 2 3 4';
  1448. eq(actual, expected, "Deleting while jumping to the next mark failed.");
  1449. });
  1450. testVim('jumpToMark_next_line_action', function(cm, vim, helpers) {
  1451. cm.setCursor(2, 2);
  1452. helpers.doKeys('m', 't');
  1453. cm.setCursor(0, 0);
  1454. helpers.doKeys('d', ']', '\'');
  1455. helpers.assertCursorAt(0, 1);
  1456. var actual = cm.getLine(0);
  1457. var expected = ' (a) [b] {c} '
  1458. eq(actual, expected, "Deleting while jumping to the next mark line failed.");
  1459. });
  1460. testVim('jumpToMark_prev', function(cm, vim, helpers) {
  1461. cm.setCursor(2, 2);
  1462. helpers.doKeys('m', 't');
  1463. cm.setCursor(4, 0);
  1464. helpers.doKeys('[', '`');
  1465. helpers.assertCursorAt(2, 2);
  1466. cm.setCursor(4, 0);
  1467. helpers.doKeys('[', '\'');
  1468. helpers.assertCursorAt(2, 0);
  1469. });
  1470. testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) {
  1471. cm.setCursor(2, 2);
  1472. helpers.doKeys('m', 'a');
  1473. cm.setCursor(3, 2);
  1474. helpers.doKeys('m', 'b');
  1475. cm.setCursor(4, 2);
  1476. helpers.doKeys('m', 'c');
  1477. cm.setCursor(5, 0);
  1478. helpers.doKeys('2', '[', '`');
  1479. helpers.assertCursorAt(3, 2);
  1480. cm.setCursor(5, 0);
  1481. helpers.doKeys('2', '[', '\'');
  1482. helpers.assertCursorAt(3, 1);
  1483. });
  1484. testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) {
  1485. cm.setCursor(2, 0);
  1486. helpers.doKeys('m', 'a');
  1487. cm.setCursor(2, 4);
  1488. helpers.doKeys('m', 'b');
  1489. cm.setCursor(2, 2);
  1490. helpers.doKeys('[', '`');
  1491. helpers.assertCursorAt(2, 0);
  1492. });
  1493. testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) {
  1494. cm.setCursor(4, 4);
  1495. helpers.doKeys('m', 'a');
  1496. cm.setCursor(2, 0);
  1497. helpers.doKeys('[', '`');
  1498. helpers.assertCursorAt(2, 0);
  1499. });
  1500. testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) {
  1501. cm.setCursor(2, 2);
  1502. helpers.doKeys('[', '`');
  1503. helpers.assertCursorAt(2, 2);
  1504. helpers.doKeys('[', '\'');
  1505. helpers.assertCursorAt(2, 0);
  1506. });
  1507. testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) {
  1508. cm.setCursor(2, 2);
  1509. helpers.doKeys('m', 'a');
  1510. cm.setCursor(3, 4);
  1511. helpers.doKeys('m', 'b');
  1512. cm.setCursor(3, 6);
  1513. helpers.doKeys('[', '\'');
  1514. helpers.assertCursorAt(2, 0);
  1515. });
  1516. testVim('delmark_single', function(cm, vim, helpers) {
  1517. cm.setCursor(1, 2);
  1518. helpers.doKeys('m', 't');
  1519. helpers.doEx('delmarks t');
  1520. cm.setCursor(0, 0);
  1521. helpers.doKeys('`', 't');
  1522. helpers.assertCursorAt(0, 0);
  1523. });
  1524. testVim('delmark_range', function(cm, vim, helpers) {
  1525. cm.setCursor(1, 2);
  1526. helpers.doKeys('m', 'a');
  1527. cm.setCursor(2, 2);
  1528. helpers.doKeys('m', 'b');
  1529. cm.setCursor(3, 2);
  1530. helpers.doKeys('m', 'c');
  1531. cm.setCursor(4, 2);
  1532. helpers.doKeys('m', 'd');
  1533. cm.setCursor(5, 2);
  1534. helpers.doKeys('m', 'e');
  1535. helpers.doEx('delmarks b-d');
  1536. cm.setCursor(0, 0);
  1537. helpers.doKeys('`', 'a');
  1538. helpers.assertCursorAt(1, 2);
  1539. helpers.doKeys('`', 'b');
  1540. helpers.assertCursorAt(1, 2);
  1541. helpers.doKeys('`', 'c');
  1542. helpers.assertCursorAt(1, 2);
  1543. helpers.doKeys('`', 'd');
  1544. helpers.assertCursorAt(1, 2);
  1545. helpers.doKeys('`', 'e');
  1546. helpers.assertCursorAt(5, 2);
  1547. });
  1548. testVim('delmark_multi', function(cm, vim, helpers) {
  1549. cm.setCursor(1, 2);
  1550. helpers.doKeys('m', 'a');
  1551. cm.setCursor(2, 2);
  1552. helpers.doKeys('m', 'b');
  1553. cm.setCursor(3, 2);
  1554. helpers.doKeys('m', 'c');
  1555. cm.setCursor(4, 2);
  1556. helpers.doKeys('m', 'd');
  1557. cm.setCursor(5, 2);
  1558. helpers.doKeys('m', 'e');
  1559. helpers.doEx('delmarks bcd');
  1560. cm.setCursor(0, 0);
  1561. helpers.doKeys('`', 'a');
  1562. helpers.assertCursorAt(1, 2);
  1563. helpers.doKeys('`', 'b');
  1564. helpers.assertCursorAt(1, 2);
  1565. helpers.doKeys('`', 'c');
  1566. helpers.assertCursorAt(1, 2);
  1567. helpers.doKeys('`', 'd');
  1568. helpers.assertCursorAt(1, 2);
  1569. helpers.doKeys('`', 'e');
  1570. helpers.assertCursorAt(5, 2);
  1571. });
  1572. testVim('delmark_multi_space', function(cm, vim, helpers) {
  1573. cm.setCursor(1, 2);
  1574. helpers.doKeys('m', 'a');
  1575. cm.setCursor(2, 2);
  1576. helpers.doKeys('m', 'b');
  1577. cm.setCursor(3, 2);
  1578. helpers.doKeys('m', 'c');
  1579. cm.setCursor(4, 2);
  1580. helpers.doKeys('m', 'd');
  1581. cm.setCursor(5, 2);
  1582. helpers.doKeys('m', 'e');
  1583. helpers.doEx('delmarks b c d');
  1584. cm.setCursor(0, 0);
  1585. helpers.doKeys('`', 'a');
  1586. helpers.assertCursorAt(1, 2);
  1587. helpers.doKeys('`', 'b');
  1588. helpers.assertCursorAt(1, 2);
  1589. helpers.doKeys('`', 'c');
  1590. helpers.assertCursorAt(1, 2);
  1591. helpers.doKeys('`', 'd');
  1592. helpers.assertCursorAt(1, 2);
  1593. helpers.doKeys('`', 'e');
  1594. helpers.assertCursorAt(5, 2);
  1595. });
  1596. testVim('delmark_all', function(cm, vim, helpers) {
  1597. cm.setCursor(1, 2);
  1598. helpers.doKeys('m', 'a');
  1599. cm.setCursor(2, 2);
  1600. helpers.doKeys('m', 'b');
  1601. cm.setCursor(3, 2);
  1602. helpers.doKeys('m', 'c');
  1603. cm.setCursor(4, 2);
  1604. helpers.doKeys('m', 'd');
  1605. cm.setCursor(5, 2);
  1606. helpers.doKeys('m', 'e');
  1607. helpers.doEx('delmarks a b-de');
  1608. cm.setCursor(0, 0);
  1609. helpers.doKeys('`', 'a');
  1610. helpers.assertCursorAt(0, 0);
  1611. helpers.doKeys('`', 'b');
  1612. helpers.assertCursorAt(0, 0);
  1613. helpers.doKeys('`', 'c');
  1614. helpers.assertCursorAt(0, 0);
  1615. helpers.doKeys('`', 'd');
  1616. helpers.assertCursorAt(0, 0);
  1617. helpers.doKeys('`', 'e');
  1618. helpers.assertCursorAt(0, 0);
  1619. });
  1620. testVim('visual', function(cm, vim, helpers) {
  1621. helpers.doKeys('l', 'v', 'l', 'l');
  1622. helpers.assertCursorAt(0, 4);
  1623. eqPos(makeCursor(0, 1), cm.getCursor('anchor'));
  1624. helpers.doKeys('d');
  1625. eq('15', cm.getValue());
  1626. }, { value: '12345' });
  1627. testVim('visual_exit', function(cm, vim, helpers) {
  1628. helpers.doKeys('<C-v>', 'l', 'j', 'j', '<Esc>');
  1629. eq(cm.getCursor('anchor'), cm.getCursor('head'));
  1630. eq(vim.visualMode, false);
  1631. }, { value: 'hello\nworld\nfoo' });
  1632. testVim('visual_line', function(cm, vim, helpers) {
  1633. helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd');
  1634. eq(' 4\n 5', cm.getValue());
  1635. }, { value: ' 1\n 2\n 3\n 4\n 5' });
  1636. testVim('visual_block', function(cm, vim, helpers) {
  1637. // test the block selection with lines of different length
  1638. // i.e. extending the selection
  1639. // till the end of the longest line.
  1640. helpers.doKeys('<C-v>', 'l', 'j', 'j', '6', 'l', 'd');
  1641. helpers.doKeys('d', 'd', 'd', 'd');
  1642. eq('', cm.getValue());
  1643. // check for left side selection in case
  1644. // of moving up to a shorter line.
  1645. cm.replaceRange('hello world\n{\nthis is\nsparta!', cm.getCursor());
  1646. cm.setCursor(3, 4);
  1647. helpers.doKeys('<C-v>', 'l', 'k', 'k', 'd');
  1648. eq('hello world\n{\ntis\nsa!', cm.getValue());
  1649. cm.replaceRange('12345\n67891\nabcde', {line: 0, ch: 0}, {line: cm.lastLine(), ch: 6});
  1650. cm.setCursor(1, 2);
  1651. helpers.doKeys('<C-v>', '2', 'l', 'k');
  1652. // circle around the anchor
  1653. // and check the selections
  1654. var selections = cm.getSelections();
  1655. eq('345891', selections.join(''));
  1656. helpers.doKeys('4', 'h');
  1657. selections = cm.getSelections();
  1658. eq('123678', selections.join(''));
  1659. helpers.doKeys('j', 'j');
  1660. selections = cm.getSelections();
  1661. eq('678abc', selections.join(''));
  1662. helpers.doKeys('4', 'l');
  1663. selections = cm.getSelections();
  1664. eq('891cde', selections.join(''));
  1665. // switch between visual modes
  1666. cm.setCursor(1, 1);
  1667. // blockwise to characterwise visual
  1668. helpers.doKeys('<C-v>', '<C-v>', 'j', 'l', 'v');
  1669. selections = cm.getSelections();
  1670. eq('7891\nabc', selections.join(''));
  1671. // characterwise to blockwise
  1672. helpers.doKeys('<C-v>');
  1673. selections = cm.getSelections();
  1674. eq('78bc', selections.join(''));
  1675. // blockwise to linewise visual
  1676. helpers.doKeys('V');
  1677. selections = cm.getSelections();
  1678. eq('67891\nabcde', selections.join(''));
  1679. }, {value: '1234\n5678\nabcdefg'});
  1680. testVim('visual_block_crossing_short_line', function(cm, vim, helpers) {
  1681. // visual block with long and short lines
  1682. cm.setCursor(0, 3);
  1683. helpers.doKeys('<C-v>', 'j', 'j', 'j');
  1684. var selections = cm.getSelections().join();
  1685. eq('4,,d,b', selections);
  1686. helpers.doKeys('3', 'k');
  1687. selections = cm.getSelections().join();
  1688. eq('4', selections);
  1689. }, {value: '123456\n78\nabcdefg\nfoobar'});
  1690. testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) {
  1691. cm.setCursor(0, 0);
  1692. helpers.doKeys('<C-v>', '3' , 'l', '<Esc>');
  1693. eqPos(makeCursor(0, 3), cm.getCursor());
  1694. }, {value: '123456\n78\nabcdefg\nfoobar'});
  1695. testVim('visual_marks', function(cm, vim, helpers) {
  1696. helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v');
  1697. // Test visual mode marks
  1698. cm.setCursor(2, 1);
  1699. helpers.doKeys('\'', '<');
  1700. helpers.assertCursorAt(0, 1);
  1701. helpers.doKeys('\'', '>');
  1702. helpers.assertCursorAt(2, 0);
  1703. });
  1704. testVim('visual_join', function(cm, vim, helpers) {
  1705. helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J');
  1706. eq(' 1 2 3\n 4\n 5', cm.getValue());
  1707. }, { value: ' 1\n 2\n 3\n 4\n 5' });
  1708. testVim('visual_blank', function(cm, vim, helpers) {
  1709. helpers.doKeys('v', 'k');
  1710. eq(vim.visualMode, true);
  1711. }, { value: '\n' });
  1712. testVim('reselect_visual', function(cm, vim, helpers) {
  1713. helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v');
  1714. helpers.assertCursorAt(0, 5);
  1715. eqPos(makeCursor(0, 1), cm.getCursor('anchor'));
  1716. helpers.doKeys('v');
  1717. cm.setCursor(1, 0);
  1718. helpers.doKeys('v', 'l', 'l', 'p');
  1719. eq('123456\n2345\nbar', cm.getValue());
  1720. cm.setCursor(0, 0);
  1721. helpers.doKeys('g', 'v');
  1722. // here the fake cursor is at (1, 3)
  1723. helpers.assertCursorAt(1, 4);
  1724. eqPos(makeCursor(1, 0), cm.getCursor('anchor'));
  1725. helpers.doKeys('v');
  1726. cm.setCursor(2, 0);
  1727. helpers.doKeys('v', 'l', 'l', 'g', 'v');
  1728. helpers.assertCursorAt(1, 4);
  1729. eqPos(makeCursor(1, 0), cm.getCursor('anchor'));
  1730. helpers.doKeys('g', 'v');
  1731. helpers.assertCursorAt(2, 3);
  1732. eqPos(makeCursor(2, 0), cm.getCursor('anchor'));
  1733. eq('123456\n2345\nbar', cm.getValue());
  1734. }, { value: '123456\nfoo\nbar' });
  1735. testVim('reselect_visual_line', function(cm, vim, helpers) {
  1736. helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd');
  1737. eq('foo\nand\nbar', cm.getValue());
  1738. cm.setCursor(1, 0);
  1739. helpers.doKeys('V', 'y', 'j');
  1740. helpers.doKeys('V', 'p' , 'g', 'v', 'd');
  1741. eq('foo\nand', cm.getValue());
  1742. }, { value: 'hello\nthis\nis\nfoo\nand\nbar' });
  1743. testVim('reselect_visual_block', function(cm, vim, helpers) {
  1744. cm.setCursor(1, 2);
  1745. helpers.doKeys('<C-v>', 'k', 'h', '<C-v>');
  1746. cm.setCursor(2, 1);
  1747. helpers.doKeys('v', 'l', 'g', 'v');
  1748. helpers.assertCursorAt(0, 1);
  1749. // Ensure selection is done with visual block mode rather than one
  1750. // continuous range.
  1751. eq(cm.getSelections().join(''), '23oo')
  1752. helpers.doKeys('g', 'v');
  1753. helpers.assertCursorAt(2, 3);
  1754. // Ensure selection of deleted range
  1755. cm.setCursor(1, 1);
  1756. helpers.doKeys('v', '<C-v>', 'j', 'd', 'g', 'v');
  1757. eq(cm.getSelections().join(''), 'or');
  1758. }, { value: '123456\nfoo\nbar' });
  1759. testVim('s_normal', function(cm, vim, helpers) {
  1760. cm.setCursor(0, 1);
  1761. helpers.doKeys('s');
  1762. helpers.doInsertModeKeys('Esc');
  1763. eq('ac', cm.getValue());
  1764. }, { value: 'abc'});
  1765. testVim('s_visual', function(cm, vim, helpers) {
  1766. cm.setCursor(0, 1);
  1767. helpers.doKeys('v', 's');
  1768. helpers.doInsertModeKeys('Esc');
  1769. helpers.assertCursorAt(0, 0);
  1770. eq('ac', cm.getValue());
  1771. }, { value: 'abc'});
  1772. testVim('o_visual', function(cm, vim, helpers) {
  1773. cm.setCursor(0,0);
  1774. helpers.doKeys('v','l','l','l','o');
  1775. helpers.assertCursorAt(0,0);
  1776. helpers.doKeys('v','v','j','j','j','o');
  1777. helpers.assertCursorAt(0,0);
  1778. helpers.doKeys('O');
  1779. helpers.doKeys('l','l')
  1780. helpers.assertCursorAt(3, 3);
  1781. helpers.doKeys('d');
  1782. eq('p',cm.getValue());
  1783. }, { value: 'abcd\nefgh\nijkl\nmnop'});
  1784. testVim('o_visual_block', function(cm, vim, helpers) {
  1785. cm.setCursor(0, 1);
  1786. helpers.doKeys('<C-v>','3','j','l','l', 'o');
  1787. helpers.assertCursorAt(0, 1);
  1788. helpers.doKeys('O');
  1789. helpers.assertCursorAt(0, 4);
  1790. helpers.doKeys('o');
  1791. helpers.assertCursorAt(3, 1);
  1792. }, { value: 'abcd\nefgh\nijkl\nmnop'});
  1793. testVim('changeCase_visual', function(cm, vim, helpers) {
  1794. cm.setCursor(0, 0);
  1795. helpers.doKeys('v', 'l', 'l');
  1796. helpers.doKeys('U');
  1797. helpers.assertCursorAt(0, 0);
  1798. helpers.doKeys('v', 'l', 'l');
  1799. helpers.doKeys('u');
  1800. helpers.assertCursorAt(0, 0);
  1801. helpers.doKeys('l', 'l', 'l', '.');
  1802. helpers.assertCursorAt(0, 3);
  1803. cm.setCursor(0, 0);
  1804. helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q');
  1805. helpers.assertCursorAt(0, 0);
  1806. helpers.doKeys('j', '@', 'a');
  1807. helpers.assertCursorAt(1, 0);
  1808. cm.setCursor(3, 0);
  1809. helpers.doKeys('V', 'U', 'j', '.');
  1810. eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue());
  1811. }, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'});
  1812. testVim('changeCase_visual_block', function(cm, vim, helpers) {
  1813. cm.setCursor(2, 1);
  1814. helpers.doKeys('<C-v>', 'k', 'k', 'h', 'U');
  1815. eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue());
  1816. cm.setCursor(0, 2);
  1817. helpers.doKeys('.');
  1818. eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue());
  1819. // check when last line is shorter.
  1820. cm.setCursor(2, 2);
  1821. helpers.doKeys('.');
  1822. eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue());
  1823. }, { value: 'abcdef\nghijkl\nmnopq\nfoo'});
  1824. testVim('visual_paste', function(cm, vim, helpers) {
  1825. cm.setCursor(0, 0);
  1826. helpers.doKeys('v', 'l', 'l', 'y', 'j', 'v', 'l', 'p');
  1827. helpers.assertCursorAt(1, 5);
  1828. eq('this is a\nunithitest for visual paste', cm.getValue());
  1829. cm.setCursor(0, 0);
  1830. // in case of pasting whole line
  1831. helpers.doKeys('y', 'y');
  1832. cm.setCursor(1, 6);
  1833. helpers.doKeys('v', 'l', 'l', 'l', 'p');
  1834. helpers.assertCursorAt(2, 0);
  1835. eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue());
  1836. }, { value: 'this is a\nunit test for visual paste'});
  1837. // This checks the contents of the register used to paste the text
  1838. testVim('v_paste_from_register', function(cm, vim, helpers) {
  1839. cm.setCursor(0, 0);
  1840. helpers.doKeys('"', 'a', 'y', 'w');
  1841. cm.setCursor(1, 0);
  1842. helpers.doKeys('v', 'p');
  1843. cm.openDialog = helpers.fakeOpenDialog('registers');
  1844. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  1845. is(/a\s+register/.test(text));
  1846. });
  1847. }, { value: 'register contents\nare not erased'});
  1848. testVim('S_normal', function(cm, vim, helpers) {
  1849. cm.setCursor(0, 1);
  1850. helpers.doKeys('j', 'S');
  1851. helpers.doInsertModeKeys('Esc');
  1852. helpers.assertCursorAt(1, 0);
  1853. eq('aa\n\ncc', cm.getValue());
  1854. }, { value: 'aa\nbb\ncc'});
  1855. testVim('blockwise_paste', function(cm, vim, helpers) {
  1856. cm.setCursor(0, 0);
  1857. helpers.doKeys('<C-v>', '3', 'j', 'l', 'y');
  1858. cm.setCursor(0, 2);
  1859. // paste one char after the current cursor position
  1860. helpers.doKeys('p');
  1861. eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue());
  1862. cm.setCursor(0, 0);
  1863. helpers.doKeys('v', '4', 'l', 'y');
  1864. cm.setCursor(0, 0);
  1865. helpers.doKeys('<C-v>', '3', 'j', 'p');
  1866. eq('helheelhelo\norwold\noofo\narba', cm.getValue());
  1867. }, { value: 'hello\nworld\nfoo\nbar'});
  1868. testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) {
  1869. // extend short lines in case of different line lengths.
  1870. cm.setCursor(0, 0);
  1871. helpers.doKeys('<C-v>', 'j', 'j', 'y');
  1872. cm.setCursor(0, 3);
  1873. helpers.doKeys('p');
  1874. eq('hellho\nfoo f\nbar b', cm.getValue());
  1875. }, { value: 'hello\nfoo\nbar'});
  1876. testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) {
  1877. cm.setCursor(0, 0);
  1878. helpers.doKeys('<C-v>', '2', 'j', 'x');
  1879. cm.setCursor(0, 0);
  1880. helpers.doKeys('P');
  1881. eq('cut\nand\npaste\nme', cm.getValue());
  1882. }, { value: 'cut\nand\npaste\nme'});
  1883. testVim('blockwise_paste_from_register', function(cm, vim, helpers) {
  1884. cm.setCursor(0, 0);
  1885. helpers.doKeys('<C-v>', '2', 'j', '"', 'a', 'y');
  1886. cm.setCursor(0, 3);
  1887. helpers.doKeys('"', 'a', 'p');
  1888. eq('foobfar\nhellho\nworlwd', cm.getValue());
  1889. }, { value: 'foobar\nhello\nworld'});
  1890. testVim('blockwise_paste_last_line', function(cm, vim, helpers) {
  1891. cm.setCursor(0, 0);
  1892. helpers.doKeys('<C-v>', '2', 'j', 'l', 'y');
  1893. cm.setCursor(3, 0);
  1894. helpers.doKeys('p');
  1895. eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue());
  1896. }, { value: 'cut\nand\npaste\nme'});
  1897. testVim('S_visual', function(cm, vim, helpers) {
  1898. cm.setCursor(0, 1);
  1899. helpers.doKeys('v', 'j', 'S');
  1900. helpers.doInsertModeKeys('Esc');
  1901. helpers.assertCursorAt(0, 0);
  1902. eq('\ncc', cm.getValue());
  1903. }, { value: 'aa\nbb\ncc'});
  1904. testVim('/ and n/N', function(cm, vim, helpers) {
  1905. cm.openDialog = helpers.fakeOpenDialog('match');
  1906. helpers.doKeys('/');
  1907. helpers.assertCursorAt(0, 11);
  1908. helpers.doKeys('n');
  1909. helpers.assertCursorAt(1, 6);
  1910. helpers.doKeys('N');
  1911. helpers.assertCursorAt(0, 11);
  1912. cm.setCursor(0, 0);
  1913. helpers.doKeys('2', '/');
  1914. helpers.assertCursorAt(1, 6);
  1915. }, { value: 'match nope match \n nope Match' });
  1916. testVim('/_case', function(cm, vim, helpers) {
  1917. cm.openDialog = helpers.fakeOpenDialog('Match');
  1918. helpers.doKeys('/');
  1919. helpers.assertCursorAt(1, 6);
  1920. }, { value: 'match nope match \n nope Match' });
  1921. testVim('/_2_pcre', function(cm, vim, helpers) {
  1922. CodeMirror.Vim.setOption('pcre', true);
  1923. cm.openDialog = helpers.fakeOpenDialog('(word){2}');
  1924. helpers.doKeys('/');
  1925. helpers.assertCursorAt(1, 9);
  1926. helpers.doKeys('n');
  1927. helpers.assertCursorAt(2, 1);
  1928. }, { value: 'word\n another wordword\n wordwordword\n' });
  1929. testVim('/_2_nopcre', function(cm, vim, helpers) {
  1930. CodeMirror.Vim.setOption('pcre', false);
  1931. cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}');
  1932. helpers.doKeys('/');
  1933. helpers.assertCursorAt(1, 9);
  1934. helpers.doKeys('n');
  1935. helpers.assertCursorAt(2, 1);
  1936. }, { value: 'word\n another wordword\n wordwordword\n' });
  1937. testVim('/_nongreedy', function(cm, vim, helpers) {
  1938. cm.openDialog = helpers.fakeOpenDialog('aa');
  1939. helpers.doKeys('/');
  1940. helpers.assertCursorAt(0, 4);
  1941. helpers.doKeys('n');
  1942. helpers.assertCursorAt(1, 3);
  1943. helpers.doKeys('n');
  1944. helpers.assertCursorAt(0, 0);
  1945. }, { value: 'aaa aa \n a aa'});
  1946. testVim('?_nongreedy', function(cm, vim, helpers) {
  1947. cm.openDialog = helpers.fakeOpenDialog('aa');
  1948. helpers.doKeys('?');
  1949. helpers.assertCursorAt(1, 3);
  1950. helpers.doKeys('n');
  1951. helpers.assertCursorAt(0, 4);
  1952. helpers.doKeys('n');
  1953. helpers.assertCursorAt(0, 0);
  1954. }, { value: 'aaa aa \n a aa'});
  1955. testVim('/_greedy', function(cm, vim, helpers) {
  1956. cm.openDialog = helpers.fakeOpenDialog('a+');
  1957. helpers.doKeys('/');
  1958. helpers.assertCursorAt(0, 4);
  1959. helpers.doKeys('n');
  1960. helpers.assertCursorAt(1, 1);
  1961. helpers.doKeys('n');
  1962. helpers.assertCursorAt(1, 3);
  1963. helpers.doKeys('n');
  1964. helpers.assertCursorAt(0, 0);
  1965. }, { value: 'aaa aa \n a aa'});
  1966. testVim('?_greedy', function(cm, vim, helpers) {
  1967. cm.openDialog = helpers.fakeOpenDialog('a+');
  1968. helpers.doKeys('?');
  1969. helpers.assertCursorAt(1, 3);
  1970. helpers.doKeys('n');
  1971. helpers.assertCursorAt(1, 1);
  1972. helpers.doKeys('n');
  1973. helpers.assertCursorAt(0, 4);
  1974. helpers.doKeys('n');
  1975. helpers.assertCursorAt(0, 0);
  1976. }, { value: 'aaa aa \n a aa'});
  1977. testVim('/_greedy_0_or_more', function(cm, vim, helpers) {
  1978. cm.openDialog = helpers.fakeOpenDialog('a*');
  1979. helpers.doKeys('/');
  1980. helpers.assertCursorAt(0, 3);
  1981. helpers.doKeys('n');
  1982. helpers.assertCursorAt(0, 4);
  1983. helpers.doKeys('n');
  1984. helpers.assertCursorAt(0, 5);
  1985. helpers.doKeys('n');
  1986. helpers.assertCursorAt(1, 0);
  1987. helpers.doKeys('n');
  1988. helpers.assertCursorAt(1, 1);
  1989. helpers.doKeys('n');
  1990. helpers.assertCursorAt(0, 0);
  1991. }, { value: 'aaa aa\n aa'});
  1992. testVim('?_greedy_0_or_more', function(cm, vim, helpers) {
  1993. cm.openDialog = helpers.fakeOpenDialog('a*');
  1994. helpers.doKeys('?');
  1995. helpers.assertCursorAt(1, 1);
  1996. helpers.doKeys('n');
  1997. helpers.assertCursorAt(1, 0);
  1998. helpers.doKeys('n');
  1999. helpers.assertCursorAt(0, 5);
  2000. helpers.doKeys('n');
  2001. helpers.assertCursorAt(0, 4);
  2002. helpers.doKeys('n');
  2003. helpers.assertCursorAt(0, 3);
  2004. helpers.doKeys('n');
  2005. helpers.assertCursorAt(0, 0);
  2006. }, { value: 'aaa aa\n aa'});
  2007. testVim('? and n/N', function(cm, vim, helpers) {
  2008. cm.openDialog = helpers.fakeOpenDialog('match');
  2009. helpers.doKeys('?');
  2010. helpers.assertCursorAt(1, 6);
  2011. helpers.doKeys('n');
  2012. helpers.assertCursorAt(0, 11);
  2013. helpers.doKeys('N');
  2014. helpers.assertCursorAt(1, 6);
  2015. cm.setCursor(0, 0);
  2016. helpers.doKeys('2', '?');
  2017. helpers.assertCursorAt(0, 11);
  2018. }, { value: 'match nope match \n nope Match' });
  2019. testVim('*', function(cm, vim, helpers) {
  2020. cm.setCursor(0, 9);
  2021. helpers.doKeys('*');
  2022. helpers.assertCursorAt(0, 22);
  2023. cm.setCursor(0, 9);
  2024. helpers.doKeys('2', '*');
  2025. helpers.assertCursorAt(1, 8);
  2026. }, { value: 'nomatch match nomatch match \nnomatch Match' });
  2027. testVim('*_no_word', function(cm, vim, helpers) {
  2028. cm.setCursor(0, 0);
  2029. helpers.doKeys('*');
  2030. helpers.assertCursorAt(0, 0);
  2031. }, { value: ' \n match \n' });
  2032. testVim('*_symbol', function(cm, vim, helpers) {
  2033. cm.setCursor(0, 0);
  2034. helpers.doKeys('*');
  2035. helpers.assertCursorAt(1, 0);
  2036. }, { value: ' /}\n/} match \n' });
  2037. testVim('#', function(cm, vim, helpers) {
  2038. cm.setCursor(0, 9);
  2039. helpers.doKeys('#');
  2040. helpers.assertCursorAt(1, 8);
  2041. cm.setCursor(0, 9);
  2042. helpers.doKeys('2', '#');
  2043. helpers.assertCursorAt(0, 22);
  2044. }, { value: 'nomatch match nomatch match \nnomatch Match' });
  2045. testVim('*_seek', function(cm, vim, helpers) {
  2046. // Should skip over space and symbols.
  2047. cm.setCursor(0, 3);
  2048. helpers.doKeys('*');
  2049. helpers.assertCursorAt(0, 22);
  2050. }, { value: ' := match nomatch match \nnomatch Match' });
  2051. testVim('#', function(cm, vim, helpers) {
  2052. // Should skip over space and symbols.
  2053. cm.setCursor(0, 3);
  2054. helpers.doKeys('#');
  2055. helpers.assertCursorAt(1, 8);
  2056. }, { value: ' := match nomatch match \nnomatch Match' });
  2057. testVim('g*', function(cm, vim, helpers) {
  2058. cm.setCursor(0, 8);
  2059. helpers.doKeys('g', '*');
  2060. helpers.assertCursorAt(0, 18);
  2061. cm.setCursor(0, 8);
  2062. helpers.doKeys('3', 'g', '*');
  2063. helpers.assertCursorAt(1, 8);
  2064. }, { value: 'matches match alsoMatch\nmatchme matching' });
  2065. testVim('g#', function(cm, vim, helpers) {
  2066. cm.setCursor(0, 8);
  2067. helpers.doKeys('g', '#');
  2068. helpers.assertCursorAt(0, 0);
  2069. cm.setCursor(0, 8);
  2070. helpers.doKeys('3', 'g', '#');
  2071. helpers.assertCursorAt(1, 0);
  2072. }, { value: 'matches match alsoMatch\nmatchme matching' });
  2073. testVim('macro_insert', function(cm, vim, helpers) {
  2074. cm.setCursor(0, 0);
  2075. helpers.doKeys('q', 'a', '0', 'i');
  2076. cm.replaceRange('foo', cm.getCursor());
  2077. helpers.doInsertModeKeys('Esc');
  2078. helpers.doKeys('q', '@', 'a');
  2079. eq('foofoo', cm.getValue());
  2080. }, { value: ''});
  2081. testVim('macro_insert_repeat', function(cm, vim, helpers) {
  2082. cm.setCursor(0, 0);
  2083. helpers.doKeys('q', 'a', '$', 'a');
  2084. cm.replaceRange('larry.', cm.getCursor());
  2085. helpers.doInsertModeKeys('Esc');
  2086. helpers.doKeys('a');
  2087. cm.replaceRange('curly.', cm.getCursor());
  2088. helpers.doInsertModeKeys('Esc');
  2089. helpers.doKeys('q');
  2090. helpers.doKeys('a');
  2091. cm.replaceRange('moe.', cm.getCursor());
  2092. helpers.doInsertModeKeys('Esc');
  2093. helpers.doKeys('@', 'a');
  2094. // At this point, the most recent edit should be the 2nd insert change
  2095. // inside the macro, i.e. "curly.".
  2096. helpers.doKeys('.');
  2097. eq('larry.curly.moe.larry.curly.curly.', cm.getValue());
  2098. }, { value: ''});
  2099. testVim('macro_space', function(cm, vim, helpers) {
  2100. cm.setCursor(0, 0);
  2101. helpers.doKeys('<Space>', '<Space>');
  2102. helpers.assertCursorAt(0, 2);
  2103. helpers.doKeys('q', 'a', '<Space>', '<Space>', 'q');
  2104. helpers.assertCursorAt(0, 4);
  2105. helpers.doKeys('@', 'a');
  2106. helpers.assertCursorAt(0, 6);
  2107. helpers.doKeys('@', 'a');
  2108. helpers.assertCursorAt(0, 8);
  2109. }, { value: 'one line of text.'});
  2110. testVim('macro_t_search', function(cm, vim, helpers) {
  2111. cm.setCursor(0, 0);
  2112. helpers.doKeys('q', 'a', 't', 'e', 'q');
  2113. helpers.assertCursorAt(0, 1);
  2114. helpers.doKeys('l', '@', 'a');
  2115. helpers.assertCursorAt(0, 6);
  2116. helpers.doKeys('l', ';');
  2117. helpers.assertCursorAt(0, 12);
  2118. }, { value: 'one line of text.'});
  2119. testVim('macro_f_search', function(cm, vim, helpers) {
  2120. cm.setCursor(0, 0);
  2121. helpers.doKeys('q', 'b', 'f', 'e', 'q');
  2122. helpers.assertCursorAt(0, 2);
  2123. helpers.doKeys('@', 'b');
  2124. helpers.assertCursorAt(0, 7);
  2125. helpers.doKeys(';');
  2126. helpers.assertCursorAt(0, 13);
  2127. }, { value: 'one line of text.'});
  2128. testVim('macro_slash_search', function(cm, vim, helpers) {
  2129. cm.setCursor(0, 0);
  2130. helpers.doKeys('q', 'c');
  2131. cm.openDialog = helpers.fakeOpenDialog('e');
  2132. helpers.doKeys('/', 'q');
  2133. helpers.assertCursorAt(0, 2);
  2134. helpers.doKeys('@', 'c');
  2135. helpers.assertCursorAt(0, 7);
  2136. helpers.doKeys('n');
  2137. helpers.assertCursorAt(0, 13);
  2138. }, { value: 'one line of text.'});
  2139. testVim('macro_multislash_search', function(cm, vim, helpers) {
  2140. cm.setCursor(0, 0);
  2141. helpers.doKeys('q', 'd');
  2142. cm.openDialog = helpers.fakeOpenDialog('e');
  2143. helpers.doKeys('/');
  2144. cm.openDialog = helpers.fakeOpenDialog('t');
  2145. helpers.doKeys('/', 'q');
  2146. helpers.assertCursorAt(0, 12);
  2147. helpers.doKeys('@', 'd');
  2148. helpers.assertCursorAt(0, 15);
  2149. }, { value: 'one line of text to rule them all.'});
  2150. testVim('macro_parens', function(cm, vim, helpers) {
  2151. cm.setCursor(0, 0);
  2152. helpers.doKeys('q', 'z', 'i');
  2153. cm.replaceRange('(', cm.getCursor());
  2154. helpers.doInsertModeKeys('Esc');
  2155. helpers.doKeys('e', 'a');
  2156. cm.replaceRange(')', cm.getCursor());
  2157. helpers.doInsertModeKeys('Esc');
  2158. helpers.doKeys('q');
  2159. helpers.doKeys('w', '@', 'z');
  2160. helpers.doKeys('w', '@', 'z');
  2161. eq('(see) (spot) (run)', cm.getValue());
  2162. }, { value: 'see spot run'});
  2163. testVim('macro_overwrite', function(cm, vim, helpers) {
  2164. cm.setCursor(0, 0);
  2165. helpers.doKeys('q', 'z', '0', 'i');
  2166. cm.replaceRange('I ', cm.getCursor());
  2167. helpers.doInsertModeKeys('Esc');
  2168. helpers.doKeys('q');
  2169. helpers.doKeys('e');
  2170. // Now replace the macro with something else.
  2171. helpers.doKeys('q', 'z', 'a');
  2172. cm.replaceRange('.', cm.getCursor());
  2173. helpers.doInsertModeKeys('Esc');
  2174. helpers.doKeys('q');
  2175. helpers.doKeys('e', '@', 'z');
  2176. helpers.doKeys('e', '@', 'z');
  2177. eq('I see. spot. run.', cm.getValue());
  2178. }, { value: 'see spot run'});
  2179. testVim('macro_search_f', function(cm, vim, helpers) {
  2180. cm.setCursor(0, 0);
  2181. helpers.doKeys('q', 'a', 'f', ' ');
  2182. helpers.assertCursorAt(0,3);
  2183. helpers.doKeys('q', '0');
  2184. helpers.assertCursorAt(0,0);
  2185. helpers.doKeys('@', 'a');
  2186. helpers.assertCursorAt(0,3);
  2187. }, { value: 'The quick brown fox jumped over the lazy dog.'});
  2188. testVim('macro_search_2f', function(cm, vim, helpers) {
  2189. cm.setCursor(0, 0);
  2190. helpers.doKeys('q', 'a', '2', 'f', ' ');
  2191. helpers.assertCursorAt(0,9);
  2192. helpers.doKeys('q', '0');
  2193. helpers.assertCursorAt(0,0);
  2194. helpers.doKeys('@', 'a');
  2195. helpers.assertCursorAt(0,9);
  2196. }, { value: 'The quick brown fox jumped over the lazy dog.'});
  2197. testVim('yank_register', function(cm, vim, helpers) {
  2198. cm.setCursor(0, 0);
  2199. helpers.doKeys('"', 'a', 'y', 'y');
  2200. helpers.doKeys('j', '"', 'b', 'y', 'y');
  2201. cm.openDialog = helpers.fakeOpenDialog('registers');
  2202. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2203. is(/a\s+foo/.test(text));
  2204. is(/b\s+bar/.test(text));
  2205. });
  2206. helpers.doKeys(':');
  2207. }, { value: 'foo\nbar'});
  2208. testVim('yank_visual_block', function(cm, vim, helpers) {
  2209. cm.setCursor(0, 1);
  2210. helpers.doKeys('<C-v>', 'l', 'j', '"', 'a', 'y');
  2211. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2212. is(/a\s+oo\nar/.test(text));
  2213. });
  2214. helpers.doKeys(':');
  2215. }, { value: 'foo\nbar'});
  2216. testVim('yank_append_line_to_line_register', function(cm, vim, helpers) {
  2217. cm.setCursor(0, 0);
  2218. helpers.doKeys('"', 'a', 'y', 'y');
  2219. helpers.doKeys('j', '"', 'A', 'y', 'y');
  2220. cm.openDialog = helpers.fakeOpenDialog('registers');
  2221. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2222. is(/a\s+foo\nbar/.test(text));
  2223. is(/"\s+foo\nbar/.test(text));
  2224. });
  2225. helpers.doKeys(':');
  2226. }, { value: 'foo\nbar'});
  2227. testVim('yank_append_word_to_word_register', function(cm, vim, helpers) {
  2228. cm.setCursor(0, 0);
  2229. helpers.doKeys('"', 'a', 'y', 'w');
  2230. helpers.doKeys('j', '"', 'A', 'y', 'w');
  2231. cm.openDialog = helpers.fakeOpenDialog('registers');
  2232. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2233. is(/a\s+foobar/.test(text));
  2234. is(/"\s+foobar/.test(text));
  2235. });
  2236. helpers.doKeys(':');
  2237. }, { value: 'foo\nbar'});
  2238. testVim('yank_append_line_to_word_register', function(cm, vim, helpers) {
  2239. cm.setCursor(0, 0);
  2240. helpers.doKeys('"', 'a', 'y', 'w');
  2241. helpers.doKeys('j', '"', 'A', 'y', 'y');
  2242. cm.openDialog = helpers.fakeOpenDialog('registers');
  2243. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2244. is(/a\s+foo\nbar/.test(text));
  2245. is(/"\s+foo\nbar/.test(text));
  2246. });
  2247. helpers.doKeys(':');
  2248. }, { value: 'foo\nbar'});
  2249. testVim('yank_append_word_to_line_register', function(cm, vim, helpers) {
  2250. cm.setCursor(0, 0);
  2251. helpers.doKeys('"', 'a', 'y', 'y');
  2252. helpers.doKeys('j', '"', 'A', 'y', 'w');
  2253. cm.openDialog = helpers.fakeOpenDialog('registers');
  2254. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2255. is(/a\s+foo\nbar/.test(text));
  2256. is(/"\s+foo\nbar/.test(text));
  2257. });
  2258. helpers.doKeys(':');
  2259. }, { value: 'foo\nbar'});
  2260. testVim('macro_register', function(cm, vim, helpers) {
  2261. cm.setCursor(0, 0);
  2262. helpers.doKeys('q', 'a', 'i');
  2263. cm.replaceRange('gangnam', cm.getCursor());
  2264. helpers.doInsertModeKeys('Esc');
  2265. helpers.doKeys('q');
  2266. helpers.doKeys('q', 'b', 'o');
  2267. cm.replaceRange('style', cm.getCursor());
  2268. helpers.doInsertModeKeys('Esc');
  2269. helpers.doKeys('q');
  2270. cm.openDialog = helpers.fakeOpenDialog('registers');
  2271. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2272. is(/a\s+i/.test(text));
  2273. is(/b\s+o/.test(text));
  2274. });
  2275. helpers.doKeys(':');
  2276. }, { value: ''});
  2277. testVim('._register', function(cm,vim,helpers) {
  2278. cm.setCursor(0,0);
  2279. helpers.doKeys('i');
  2280. cm.replaceRange('foo',cm.getCursor());
  2281. helpers.doInsertModeKeys('Esc');
  2282. cm.openDialog = helpers.fakeOpenDialog('registers');
  2283. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2284. is(/\.\s+foo/.test(text));
  2285. });
  2286. helpers.doKeys(':');
  2287. }, {value: ''});
  2288. testVim(':_register', function(cm,vim,helpers) {
  2289. helpers.doEx('bar');
  2290. cm.openDialog = helpers.fakeOpenDialog('registers');
  2291. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2292. is(/:\s+bar/.test(text));
  2293. });
  2294. helpers.doKeys(':');
  2295. }, {value: ''});
  2296. testVim('search_register_escape', function(cm, vim, helpers) {
  2297. // Check that the register is restored if the user escapes rather than confirms.
  2298. cm.openDialog = helpers.fakeOpenDialog('waldo');
  2299. helpers.doKeys('/');
  2300. var onKeyDown;
  2301. var onKeyUp;
  2302. var KEYCODES = {
  2303. f: 70,
  2304. o: 79,
  2305. Esc: 27
  2306. };
  2307. cm.openDialog = function(template, callback, options) {
  2308. onKeyDown = options.onKeyDown;
  2309. onKeyUp = options.onKeyUp;
  2310. };
  2311. var close = function() {};
  2312. helpers.doKeys('/');
  2313. // Fake some keyboard events coming in.
  2314. onKeyDown({keyCode: KEYCODES.f}, '', close);
  2315. onKeyUp({keyCode: KEYCODES.f}, '', close);
  2316. onKeyDown({keyCode: KEYCODES.o}, 'f', close);
  2317. onKeyUp({keyCode: KEYCODES.o}, 'f', close);
  2318. onKeyDown({keyCode: KEYCODES.o}, 'fo', close);
  2319. onKeyUp({keyCode: KEYCODES.o}, 'fo', close);
  2320. onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close);
  2321. cm.openDialog = helpers.fakeOpenDialog('registers');
  2322. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2323. is(/waldo/.test(text));
  2324. is(!/foo/.test(text));
  2325. });
  2326. helpers.doKeys(':');
  2327. }, {value: ''});
  2328. testVim('search_register', function(cm, vim, helpers) {
  2329. cm.openDialog = helpers.fakeOpenDialog('foo');
  2330. helpers.doKeys('/');
  2331. cm.openDialog = helpers.fakeOpenDialog('registers');
  2332. cm.openNotification = helpers.fakeOpenNotification(function(text) {
  2333. is(/\/\s+foo/.test(text));
  2334. });
  2335. helpers.doKeys(':');
  2336. }, {value: ''});
  2337. testVim('search_history', function(cm, vim, helpers) {
  2338. cm.openDialog = helpers.fakeOpenDialog('this');
  2339. helpers.doKeys('/');
  2340. cm.openDialog = helpers.fakeOpenDialog('checks');
  2341. helpers.doKeys('/');
  2342. cm.openDialog = helpers.fakeOpenDialog('search');
  2343. helpers.doKeys('/');
  2344. cm.openDialog = helpers.fakeOpenDialog('history');
  2345. helpers.doKeys('/');
  2346. cm.openDialog = helpers.fakeOpenDialog('checks');
  2347. helpers.doKeys('/');
  2348. var onKeyDown;
  2349. var onKeyUp;
  2350. var query = '';
  2351. var keyCodes = {
  2352. Up: 38,
  2353. Down: 40
  2354. };
  2355. cm.openDialog = function(template, callback, options) {
  2356. onKeyUp = options.onKeyUp;
  2357. onKeyDown = options.onKeyDown;
  2358. };
  2359. var close = function(newVal) {
  2360. if (typeof newVal == 'string') query = newVal;
  2361. }
  2362. helpers.doKeys('/');
  2363. onKeyDown({keyCode: keyCodes.Up}, query, close);
  2364. onKeyUp({keyCode: keyCodes.Up}, query, close);
  2365. eq(query, 'checks');
  2366. onKeyDown({keyCode: keyCodes.Up}, query, close);
  2367. onKeyUp({keyCode: keyCodes.Up}, query, close);
  2368. eq(query, 'history');
  2369. onKeyDown({keyCode: keyCodes.Up}, query, close);
  2370. onKeyUp({keyCode: keyCodes.Up}, query, close);
  2371. eq(query, 'search');
  2372. onKeyDown({keyCode: keyCodes.Up}, query, close);
  2373. onKeyUp({keyCode: keyCodes.Up}, query, close);
  2374. eq(query, 'this');
  2375. onKeyDown({keyCode: keyCodes.Down}, query, close);
  2376. onKeyUp({keyCode: keyCodes.Down}, query, close);
  2377. eq(query, 'search');
  2378. }, {value: ''});
  2379. testVim('exCommand_history', function(cm, vim, helpers) {
  2380. cm.openDialog = helpers.fakeOpenDialog('registers');
  2381. helpers.doKeys(':');
  2382. cm.openDialog = helpers.fakeOpenDialog('sort');
  2383. helpers.doKeys(':');
  2384. cm.openDialog = helpers.fakeOpenDialog('map');
  2385. helpers.doKeys(':');
  2386. cm.openDialog = helpers.fakeOpenDialog('invalid');
  2387. helpers.doKeys(':');
  2388. var onKeyDown;
  2389. var onKeyUp;
  2390. var input = '';
  2391. var keyCodes = {
  2392. Up: 38,
  2393. Down: 40,
  2394. s: 115
  2395. };
  2396. cm.openDialog = function(template, callback, options) {
  2397. onKeyUp = options.onKeyUp;
  2398. onKeyDown = options.onKeyDown;
  2399. };
  2400. var close = function(newVal) {
  2401. if (typeof newVal == 'string') input = newVal;
  2402. }
  2403. helpers.doKeys(':');
  2404. onKeyDown({keyCode: keyCodes.Up}, input, close);
  2405. eq(input, 'invalid');
  2406. onKeyDown({keyCode: keyCodes.Up}, input, close);
  2407. eq(input, 'map');
  2408. onKeyDown({keyCode: keyCodes.Up}, input, close);
  2409. eq(input, 'sort');
  2410. onKeyDown({keyCode: keyCodes.Up}, input, close);
  2411. eq(input, 'registers');
  2412. onKeyDown({keyCode: keyCodes.s}, '', close);
  2413. input = 's';
  2414. onKeyDown({keyCode: keyCodes.Up}, input, close);
  2415. eq(input, 'sort');
  2416. }, {value: ''});
  2417. testVim('.', function(cm, vim, helpers) {
  2418. cm.setCursor(0, 0);
  2419. helpers.doKeys('2', 'd', 'w');
  2420. helpers.doKeys('.');
  2421. eq('5 6', cm.getValue());
  2422. }, { value: '1 2 3 4 5 6'});
  2423. testVim('._repeat', function(cm, vim, helpers) {
  2424. cm.setCursor(0, 0);
  2425. helpers.doKeys('2', 'd', 'w');
  2426. helpers.doKeys('3', '.');
  2427. eq('6', cm.getValue());
  2428. }, { value: '1 2 3 4 5 6'});
  2429. testVim('._insert', function(cm, vim, helpers) {
  2430. helpers.doKeys('i');
  2431. cm.replaceRange('test', cm.getCursor());
  2432. helpers.doInsertModeKeys('Esc');
  2433. helpers.doKeys('.');
  2434. eq('testestt', cm.getValue());
  2435. helpers.assertCursorAt(0, 6);
  2436. }, { value: ''});
  2437. testVim('._insert_repeat', function(cm, vim, helpers) {
  2438. helpers.doKeys('i');
  2439. cm.replaceRange('test', cm.getCursor());
  2440. cm.setCursor(0, 4);
  2441. helpers.doInsertModeKeys('Esc');
  2442. helpers.doKeys('2', '.');
  2443. eq('testesttestt', cm.getValue());
  2444. helpers.assertCursorAt(0, 10);
  2445. }, { value: ''});
  2446. testVim('._repeat_insert', function(cm, vim, helpers) {
  2447. helpers.doKeys('3', 'i');
  2448. cm.replaceRange('te', cm.getCursor());
  2449. cm.setCursor(0, 2);
  2450. helpers.doInsertModeKeys('Esc');
  2451. helpers.doKeys('.');
  2452. eq('tetettetetee', cm.getValue());
  2453. helpers.assertCursorAt(0, 10);
  2454. }, { value: ''});
  2455. testVim('._insert_o', function(cm, vim, helpers) {
  2456. helpers.doKeys('o');
  2457. cm.replaceRange('z', cm.getCursor());
  2458. cm.setCursor(1, 1);
  2459. helpers.doInsertModeKeys('Esc');
  2460. helpers.doKeys('.');
  2461. eq('\nz\nz', cm.getValue());
  2462. helpers.assertCursorAt(2, 0);
  2463. }, { value: ''});
  2464. testVim('._insert_o_repeat', function(cm, vim, helpers) {
  2465. helpers.doKeys('o');
  2466. cm.replaceRange('z', cm.getCursor());
  2467. helpers.doInsertModeKeys('Esc');
  2468. cm.setCursor(1, 0);
  2469. helpers.doKeys('2', '.');
  2470. eq('\nz\nz\nz', cm.getValue());
  2471. helpers.assertCursorAt(3, 0);
  2472. }, { value: ''});
  2473. testVim('._insert_o_indent', function(cm, vim, helpers) {
  2474. helpers.doKeys('o');
  2475. cm.replaceRange('z', cm.getCursor());
  2476. helpers.doInsertModeKeys('Esc');
  2477. cm.setCursor(1, 2);
  2478. helpers.doKeys('.');
  2479. eq('{\n z\n z', cm.getValue());
  2480. helpers.assertCursorAt(2, 2);
  2481. }, { value: '{'});
  2482. testVim('._insert_cw', function(cm, vim, helpers) {
  2483. helpers.doKeys('c', 'w');
  2484. cm.replaceRange('test', cm.getCursor());
  2485. helpers.doInsertModeKeys('Esc');
  2486. cm.setCursor(0, 3);
  2487. helpers.doKeys('2', 'l');
  2488. helpers.doKeys('.');
  2489. eq('test test word3', cm.getValue());
  2490. helpers.assertCursorAt(0, 8);
  2491. }, { value: 'word1 word2 word3' });
  2492. testVim('._insert_cw_repeat', function(cm, vim, helpers) {
  2493. // For some reason, repeat cw in desktop VIM will does not repeat insert mode
  2494. // changes. Will conform to that behavior.
  2495. helpers.doKeys('c', 'w');
  2496. cm.replaceRange('test', cm.getCursor());
  2497. helpers.doInsertModeKeys('Esc');
  2498. cm.setCursor(0, 4);
  2499. helpers.doKeys('l');
  2500. helpers.doKeys('2', '.');
  2501. eq('test test', cm.getValue());
  2502. helpers.assertCursorAt(0, 8);
  2503. }, { value: 'word1 word2 word3' });
  2504. testVim('._delete', function(cm, vim, helpers) {
  2505. cm.setCursor(0, 5);
  2506. helpers.doKeys('i');
  2507. helpers.doInsertModeKeys('Backspace', 'Esc');
  2508. helpers.doKeys('.');
  2509. eq('zace', cm.getValue());
  2510. helpers.assertCursorAt(0, 1);
  2511. }, { value: 'zabcde'});
  2512. testVim('._delete_repeat', function(cm, vim, helpers) {
  2513. cm.setCursor(0, 6);
  2514. helpers.doKeys('i');
  2515. helpers.doInsertModeKeys('Backspace', 'Esc');
  2516. helpers.doKeys('2', '.');
  2517. eq('zzce', cm.getValue());
  2518. helpers.assertCursorAt(0, 1);
  2519. }, { value: 'zzabcde'});
  2520. testVim('._visual_>', function(cm, vim, helpers) {
  2521. cm.setCursor(0, 0);
  2522. helpers.doKeys('V', 'j', '>');
  2523. cm.setCursor(2, 0)
  2524. helpers.doKeys('.');
  2525. eq(' 1\n 2\n 3\n 4', cm.getValue());
  2526. helpers.assertCursorAt(2, 2);
  2527. }, { value: '1\n2\n3\n4'});
  2528. testVim('f;', function(cm, vim, helpers) {
  2529. cm.setCursor(0, 0);
  2530. helpers.doKeys('f', 'x');
  2531. helpers.doKeys(';');
  2532. helpers.doKeys('2', ';');
  2533. eq(9, cm.getCursor().ch);
  2534. }, { value: '01x3xx678x'});
  2535. testVim('F;', function(cm, vim, helpers) {
  2536. cm.setCursor(0, 8);
  2537. helpers.doKeys('F', 'x');
  2538. helpers.doKeys(';');
  2539. helpers.doKeys('2', ';');
  2540. eq(2, cm.getCursor().ch);
  2541. }, { value: '01x3xx6x8x'});
  2542. testVim('t;', function(cm, vim, helpers) {
  2543. cm.setCursor(0, 0);
  2544. helpers.doKeys('t', 'x');
  2545. helpers.doKeys(';');
  2546. helpers.doKeys('2', ';');
  2547. eq(8, cm.getCursor().ch);
  2548. }, { value: '01x3xx678x'});
  2549. testVim('T;', function(cm, vim, helpers) {
  2550. cm.setCursor(0, 9);
  2551. helpers.doKeys('T', 'x');
  2552. helpers.doKeys(';');
  2553. helpers.doKeys('2', ';');
  2554. eq(2, cm.getCursor().ch);
  2555. }, { value: '0xx3xx678x'});
  2556. testVim('f,', function(cm, vim, helpers) {
  2557. cm.setCursor(0, 6);
  2558. helpers.doKeys('f', 'x');
  2559. helpers.doKeys(',');
  2560. helpers.doKeys('2', ',');
  2561. eq(2, cm.getCursor().ch);
  2562. }, { value: '01x3xx678x'});
  2563. testVim('F,', function(cm, vim, helpers) {
  2564. cm.setCursor(0, 3);
  2565. helpers.doKeys('F', 'x');
  2566. helpers.doKeys(',');
  2567. helpers.doKeys('2', ',');
  2568. eq(9, cm.getCursor().ch);
  2569. }, { value: '01x3xx678x'});
  2570. testVim('t,', function(cm, vim, helpers) {
  2571. cm.setCursor(0, 6);
  2572. helpers.doKeys('t', 'x');
  2573. helpers.doKeys(',');
  2574. helpers.doKeys('2', ',');
  2575. eq(3, cm.getCursor().ch);
  2576. }, { value: '01x3xx678x'});
  2577. testVim('T,', function(cm, vim, helpers) {
  2578. cm.setCursor(0, 4);
  2579. helpers.doKeys('T', 'x');
  2580. helpers.doKeys(',');
  2581. helpers.doKeys('2', ',');
  2582. eq(8, cm.getCursor().ch);
  2583. }, { value: '01x3xx67xx'});
  2584. testVim('fd,;', function(cm, vim, helpers) {
  2585. cm.setCursor(0, 0);
  2586. helpers.doKeys('f', '4');
  2587. cm.setCursor(0, 0);
  2588. helpers.doKeys('d', ';');
  2589. eq('56789', cm.getValue());
  2590. helpers.doKeys('u');
  2591. cm.setCursor(0, 9);
  2592. helpers.doKeys('d', ',');
  2593. eq('01239', cm.getValue());
  2594. }, { value: '0123456789'});
  2595. testVim('Fd,;', function(cm, vim, helpers) {
  2596. cm.setCursor(0, 9);
  2597. helpers.doKeys('F', '4');
  2598. cm.setCursor(0, 9);
  2599. helpers.doKeys('d', ';');
  2600. eq('01239', cm.getValue());
  2601. helpers.doKeys('u');
  2602. cm.setCursor(0, 0);
  2603. helpers.doKeys('d', ',');
  2604. eq('56789', cm.getValue());
  2605. }, { value: '0123456789'});
  2606. testVim('td,;', function(cm, vim, helpers) {
  2607. cm.setCursor(0, 0);
  2608. helpers.doKeys('t', '4');
  2609. cm.setCursor(0, 0);
  2610. helpers.doKeys('d', ';');
  2611. eq('456789', cm.getValue());
  2612. helpers.doKeys('u');
  2613. cm.setCursor(0, 9);
  2614. helpers.doKeys('d', ',');
  2615. eq('012349', cm.getValue());
  2616. }, { value: '0123456789'});
  2617. testVim('Td,;', function(cm, vim, helpers) {
  2618. cm.setCursor(0, 9);
  2619. helpers.doKeys('T', '4');
  2620. cm.setCursor(0, 9);
  2621. helpers.doKeys('d', ';');
  2622. eq('012349', cm.getValue());
  2623. helpers.doKeys('u');
  2624. cm.setCursor(0, 0);
  2625. helpers.doKeys('d', ',');
  2626. eq('456789', cm.getValue());
  2627. }, { value: '0123456789'});
  2628. testVim('fc,;', function(cm, vim, helpers) {
  2629. cm.setCursor(0, 0);
  2630. helpers.doKeys('f', '4');
  2631. cm.setCursor(0, 0);
  2632. helpers.doKeys('c', ';', 'Esc');
  2633. eq('56789', cm.getValue());
  2634. helpers.doKeys('u');
  2635. cm.setCursor(0, 9);
  2636. helpers.doKeys('c', ',');
  2637. eq('01239', cm.getValue());
  2638. }, { value: '0123456789'});
  2639. testVim('Fc,;', function(cm, vim, helpers) {
  2640. cm.setCursor(0, 9);
  2641. helpers.doKeys('F', '4');
  2642. cm.setCursor(0, 9);
  2643. helpers.doKeys('c', ';', 'Esc');
  2644. eq('01239', cm.getValue());
  2645. helpers.doKeys('u');
  2646. cm.setCursor(0, 0);
  2647. helpers.doKeys('c', ',');
  2648. eq('56789', cm.getValue());
  2649. }, { value: '0123456789'});
  2650. testVim('tc,;', function(cm, vim, helpers) {
  2651. cm.setCursor(0, 0);
  2652. helpers.doKeys('t', '4');
  2653. cm.setCursor(0, 0);
  2654. helpers.doKeys('c', ';', 'Esc');
  2655. eq('456789', cm.getValue());
  2656. helpers.doKeys('u');
  2657. cm.setCursor(0, 9);
  2658. helpers.doKeys('c', ',');
  2659. eq('012349', cm.getValue());
  2660. }, { value: '0123456789'});
  2661. testVim('Tc,;', function(cm, vim, helpers) {
  2662. cm.setCursor(0, 9);
  2663. helpers.doKeys('T', '4');
  2664. cm.setCursor(0, 9);
  2665. helpers.doKeys('c', ';', 'Esc');
  2666. eq('012349', cm.getValue());
  2667. helpers.doKeys('u');
  2668. cm.setCursor(0, 0);
  2669. helpers.doKeys('c', ',');
  2670. eq('456789', cm.getValue());
  2671. }, { value: '0123456789'});
  2672. testVim('fy,;', function(cm, vim, helpers) {
  2673. cm.setCursor(0, 0);
  2674. helpers.doKeys('f', '4');
  2675. cm.setCursor(0, 0);
  2676. helpers.doKeys('y', ';', 'P');
  2677. eq('012340123456789', cm.getValue());
  2678. helpers.doKeys('u');
  2679. cm.setCursor(0, 9);
  2680. helpers.doKeys('y', ',', 'P');
  2681. eq('012345678456789', cm.getValue());
  2682. }, { value: '0123456789'});
  2683. testVim('Fy,;', function(cm, vim, helpers) {
  2684. cm.setCursor(0, 9);
  2685. helpers.doKeys('F', '4');
  2686. cm.setCursor(0, 9);
  2687. helpers.doKeys('y', ';', 'p');
  2688. eq('012345678945678', cm.getValue());
  2689. helpers.doKeys('u');
  2690. cm.setCursor(0, 0);
  2691. helpers.doKeys('y', ',', 'P');
  2692. eq('012340123456789', cm.getValue());
  2693. }, { value: '0123456789'});
  2694. testVim('ty,;', function(cm, vim, helpers) {
  2695. cm.setCursor(0, 0);
  2696. helpers.doKeys('t', '4');
  2697. cm.setCursor(0, 0);
  2698. helpers.doKeys('y', ';', 'P');
  2699. eq('01230123456789', cm.getValue());
  2700. helpers.doKeys('u');
  2701. cm.setCursor(0, 9);
  2702. helpers.doKeys('y', ',', 'p');
  2703. eq('01234567895678', cm.getValue());
  2704. }, { value: '0123456789'});
  2705. testVim('Ty,;', function(cm, vim, helpers) {
  2706. cm.setCursor(0, 9);
  2707. helpers.doKeys('T', '4');
  2708. cm.setCursor(0, 9);
  2709. helpers.doKeys('y', ';', 'p');
  2710. eq('01234567895678', cm.getValue());
  2711. helpers.doKeys('u');
  2712. cm.setCursor(0, 0);
  2713. helpers.doKeys('y', ',', 'P');
  2714. eq('01230123456789', cm.getValue());
  2715. }, { value: '0123456789'});
  2716. testVim('HML', function(cm, vim, helpers) {
  2717. var lines = 35;
  2718. var textHeight = cm.defaultTextHeight();
  2719. cm.setSize(600, lines*textHeight);
  2720. cm.setCursor(120, 0);
  2721. helpers.doKeys('H');
  2722. helpers.assertCursorAt(86, 2);
  2723. helpers.doKeys('L');
  2724. helpers.assertCursorAt(120, 4);
  2725. helpers.doKeys('M');
  2726. helpers.assertCursorAt(103,4);
  2727. }, { value: (function(){
  2728. var lines = new Array(100);
  2729. var upper = ' xx\n';
  2730. var lower = ' xx\n';
  2731. upper = lines.join(upper);
  2732. lower = lines.join(lower);
  2733. return upper + lower;
  2734. })()});
  2735. var zVals = [];
  2736. forEach(['zb','zz','zt','z-','z.','z<CR>'], function(e, idx){
  2737. var lineNum = 250;
  2738. var lines = 35;
  2739. testVim(e, function(cm, vim, helpers) {
  2740. var k1 = e[0];
  2741. var k2 = e.substring(1);
  2742. var textHeight = cm.defaultTextHeight();
  2743. cm.setSize(600, lines*textHeight);
  2744. cm.setCursor(lineNum, 0);
  2745. helpers.doKeys(k1, k2);
  2746. zVals[idx] = cm.getScrollInfo().top;
  2747. }, { value: (function(){
  2748. return new Array(500).join('\n');
  2749. })()});
  2750. });
  2751. testVim('zb<zz', function(cm, vim, helpers){
  2752. eq(zVals[0]<zVals[1], true);
  2753. });
  2754. testVim('zz<zt', function(cm, vim, helpers){
  2755. eq(zVals[1]<zVals[2], true);
  2756. });
  2757. testVim('zb==z-', function(cm, vim, helpers){
  2758. eq(zVals[0], zVals[3]);
  2759. });
  2760. testVim('zz==z.', function(cm, vim, helpers){
  2761. eq(zVals[1], zVals[4]);
  2762. });
  2763. testVim('zt==z<CR>', function(cm, vim, helpers){
  2764. eq(zVals[2], zVals[5]);
  2765. });
  2766. var moveTillCharacterSandbox =
  2767. 'The quick brown fox \n'
  2768. 'jumped over the lazy dog.'
  2769. testVim('moveTillCharacter', function(cm, vim, helpers){
  2770. cm.setCursor(0, 0);
  2771. // Search for the 'q'.
  2772. cm.openDialog = helpers.fakeOpenDialog('q');
  2773. helpers.doKeys('/');
  2774. eq(4, cm.getCursor().ch);
  2775. // Jump to just before the first o in the list.
  2776. helpers.doKeys('t');
  2777. helpers.doKeys('o');
  2778. eq('The quick brown fox \n', cm.getValue());
  2779. // Delete that one character.
  2780. helpers.doKeys('d');
  2781. helpers.doKeys('t');
  2782. helpers.doKeys('o');
  2783. eq('The quick bown fox \n', cm.getValue());
  2784. // Delete everything until the next 'o'.
  2785. helpers.doKeys('.');
  2786. eq('The quick box \n', cm.getValue());
  2787. // An unmatched character should have no effect.
  2788. helpers.doKeys('d');
  2789. helpers.doKeys('t');
  2790. helpers.doKeys('q');
  2791. eq('The quick box \n', cm.getValue());
  2792. // Matches should only be possible on single lines.
  2793. helpers.doKeys('d');
  2794. helpers.doKeys('t');
  2795. helpers.doKeys('z');
  2796. eq('The quick box \n', cm.getValue());
  2797. // After all that, the search for 'q' should still be active, so the 'N' command
  2798. // can run it again in reverse. Use that to delete everything back to the 'q'.
  2799. helpers.doKeys('d');
  2800. helpers.doKeys('N');
  2801. eq('The ox \n', cm.getValue());
  2802. eq(4, cm.getCursor().ch);
  2803. }, { value: moveTillCharacterSandbox});
  2804. testVim('searchForPipe', function(cm, vim, helpers){
  2805. CodeMirror.Vim.setOption('pcre', false);
  2806. cm.setCursor(0, 0);
  2807. // Search for the '|'.
  2808. cm.openDialog = helpers.fakeOpenDialog('|');
  2809. helpers.doKeys('/');
  2810. eq(4, cm.getCursor().ch);
  2811. }, { value: 'this|that'});
  2812. var scrollMotionSandbox =
  2813. '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
  2814. '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
  2815. '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
  2816. '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n';
  2817. testVim('scrollMotion', function(cm, vim, helpers){
  2818. var prevCursor, prevScrollInfo;
  2819. cm.setCursor(0, 0);
  2820. // ctrl-y at the top of the file should have no effect.
  2821. helpers.doKeys('<C-y>');
  2822. eq(0, cm.getCursor().line);
  2823. prevScrollInfo = cm.getScrollInfo();
  2824. helpers.doKeys('<C-e>');
  2825. eq(1, cm.getCursor().line);
  2826. is(prevScrollInfo.top < cm.getScrollInfo().top);
  2827. // Jump to the end of the sandbox.
  2828. cm.setCursor(1000, 0);
  2829. prevCursor = cm.getCursor();
  2830. // ctrl-e at the bottom of the file should have no effect.
  2831. helpers.doKeys('<C-e>');
  2832. eq(prevCursor.line, cm.getCursor().line);
  2833. prevScrollInfo = cm.getScrollInfo();
  2834. helpers.doKeys('<C-y>');
  2835. eq(prevCursor.line - 1, cm.getCursor().line);
  2836. is(prevScrollInfo.top > cm.getScrollInfo().top);
  2837. }, { value: scrollMotionSandbox});
  2838. var squareBracketMotionSandbox = ''+
  2839. '({\n'+//0
  2840. ' ({\n'+//11
  2841. ' /*comment {\n'+//2
  2842. ' */(\n'+//3
  2843. '#else \n'+//4
  2844. ' /* )\n'+//5
  2845. '#if }\n'+//6
  2846. ' )}*/\n'+//7
  2847. ')}\n'+//8
  2848. '{}\n'+//9
  2849. '#else {{\n'+//10
  2850. '{}\n'+//11
  2851. '}\n'+//12
  2852. '{\n'+//13
  2853. '#endif\n'+//14
  2854. '}\n'+//15
  2855. '}\n'+//16
  2856. '#else';//17
  2857. testVim('[[, ]]', function(cm, vim, helpers) {
  2858. cm.setCursor(0, 0);
  2859. helpers.doKeys(']', ']');
  2860. helpers.assertCursorAt(9,0);
  2861. helpers.doKeys('2', ']', ']');
  2862. helpers.assertCursorAt(13,0);
  2863. helpers.doKeys(']', ']');
  2864. helpers.assertCursorAt(17,0);
  2865. helpers.doKeys('[', '[');
  2866. helpers.assertCursorAt(13,0);
  2867. helpers.doKeys('2', '[', '[');
  2868. helpers.assertCursorAt(9,0);
  2869. helpers.doKeys('[', '[');
  2870. helpers.assertCursorAt(0,0);
  2871. }, { value: squareBracketMotionSandbox});
  2872. testVim('[], ][', function(cm, vim, helpers) {
  2873. cm.setCursor(0, 0);
  2874. helpers.doKeys(']', '[');
  2875. helpers.assertCursorAt(12,0);
  2876. helpers.doKeys('2', ']', '[');
  2877. helpers.assertCursorAt(16,0);
  2878. helpers.doKeys(']', '[');
  2879. helpers.assertCursorAt(17,0);
  2880. helpers.doKeys('[', ']');
  2881. helpers.assertCursorAt(16,0);
  2882. helpers.doKeys('2', '[', ']');
  2883. helpers.assertCursorAt(12,0);
  2884. helpers.doKeys('[', ']');
  2885. helpers.assertCursorAt(0,0);
  2886. }, { value: squareBracketMotionSandbox});
  2887. testVim('[{, ]}', function(cm, vim, helpers) {
  2888. cm.setCursor(4, 10);
  2889. helpers.doKeys('[', '{');
  2890. helpers.assertCursorAt(2,12);
  2891. helpers.doKeys('2', '[', '{');
  2892. helpers.assertCursorAt(0,1);
  2893. cm.setCursor(4, 10);
  2894. helpers.doKeys(']', '}');
  2895. helpers.assertCursorAt(6,11);
  2896. helpers.doKeys('2', ']', '}');
  2897. helpers.assertCursorAt(8,1);
  2898. cm.setCursor(0,1);
  2899. helpers.doKeys(']', '}');
  2900. helpers.assertCursorAt(8,1);
  2901. helpers.doKeys('[', '{');
  2902. helpers.assertCursorAt(0,1);
  2903. }, { value: squareBracketMotionSandbox});
  2904. testVim('[(, ])', function(cm, vim, helpers) {
  2905. cm.setCursor(4, 10);
  2906. helpers.doKeys('[', '(');
  2907. helpers.assertCursorAt(3,14);
  2908. helpers.doKeys('2', '[', '(');
  2909. helpers.assertCursorAt(0,0);
  2910. cm.setCursor(4, 10);
  2911. helpers.doKeys(']', ')');
  2912. helpers.assertCursorAt(5,11);
  2913. helpers.doKeys('2', ']', ')');
  2914. helpers.assertCursorAt(8,0);
  2915. helpers.doKeys('[', '(');
  2916. helpers.assertCursorAt(0,0);
  2917. helpers.doKeys(']', ')');
  2918. helpers.assertCursorAt(8,0);
  2919. }, { value: squareBracketMotionSandbox});
  2920. testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) {
  2921. forEach(['*', '/'], function(key){
  2922. cm.setCursor(7, 0);
  2923. helpers.doKeys('2', '[', key);
  2924. helpers.assertCursorAt(2,2);
  2925. helpers.doKeys('2', ']', key);
  2926. helpers.assertCursorAt(7,5);
  2927. });
  2928. }, { value: squareBracketMotionSandbox});
  2929. testVim('[#, ]#', function(cm, vim, helpers) {
  2930. cm.setCursor(10, 3);
  2931. helpers.doKeys('2', '[', '#');
  2932. helpers.assertCursorAt(4,0);
  2933. helpers.doKeys('5', ']', '#');
  2934. helpers.assertCursorAt(17,0);
  2935. cm.setCursor(10, 3);
  2936. helpers.doKeys(']', '#');
  2937. helpers.assertCursorAt(14,0);
  2938. }, { value: squareBracketMotionSandbox});
  2939. testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) {
  2940. cm.setCursor(11, 0);
  2941. helpers.doKeys('[', 'm');
  2942. helpers.assertCursorAt(10,7);
  2943. helpers.doKeys('4', '[', 'm');
  2944. helpers.assertCursorAt(1,3);
  2945. helpers.doKeys('5', ']', 'm');
  2946. helpers.assertCursorAt(11,0);
  2947. helpers.doKeys('[', 'M');
  2948. helpers.assertCursorAt(9,1);
  2949. helpers.doKeys('3', ']', 'M');
  2950. helpers.assertCursorAt(15,0);
  2951. helpers.doKeys('5', '[', 'M');
  2952. helpers.assertCursorAt(7,3);
  2953. }, { value: squareBracketMotionSandbox});
  2954. // Ex mode tests
  2955. testVim('ex_go_to_line', function(cm, vim, helpers) {
  2956. cm.setCursor(0, 0);
  2957. helpers.doEx('4');
  2958. helpers.assertCursorAt(3, 0);
  2959. }, { value: 'a\nb\nc\nd\ne\n'});
  2960. testVim('ex_write', function(cm, vim, helpers) {
  2961. var tmp = CodeMirror.commands.save;
  2962. var written;
  2963. var actualCm;
  2964. CodeMirror.commands.save = function(cm) {
  2965. written = true;
  2966. actualCm = cm;
  2967. };
  2968. // Test that w, wr, wri ... write all trigger :write.
  2969. var command = 'write';
  2970. for (var i = 1; i < command.length; i++) {
  2971. written = false;
  2972. actualCm = null;
  2973. helpers.doEx(command.substring(0, i));
  2974. eq(written, true);
  2975. eq(actualCm, cm);
  2976. }
  2977. CodeMirror.commands.save = tmp;
  2978. });
  2979. testVim('ex_sort', function(cm, vim, helpers) {
  2980. helpers.doEx('sort');
  2981. eq('Z\na\nb\nc\nd', cm.getValue());
  2982. }, { value: 'b\nZ\nd\nc\na'});
  2983. testVim('ex_sort_reverse', function(cm, vim, helpers) {
  2984. helpers.doEx('sort!');
  2985. eq('d\nc\nb\na', cm.getValue());
  2986. }, { value: 'b\nd\nc\na'});
  2987. testVim('ex_sort_range', function(cm, vim, helpers) {
  2988. helpers.doEx('2,3sort');
  2989. eq('b\nc\nd\na', cm.getValue());
  2990. }, { value: 'b\nd\nc\na'});
  2991. testVim('ex_sort_oneline', function(cm, vim, helpers) {
  2992. helpers.doEx('2sort');
  2993. // Expect no change.
  2994. eq('b\nd\nc\na', cm.getValue());
  2995. }, { value: 'b\nd\nc\na'});
  2996. testVim('ex_sort_ignoreCase', function(cm, vim, helpers) {
  2997. helpers.doEx('sort i');
  2998. eq('a\nb\nc\nd\nZ', cm.getValue());
  2999. }, { value: 'b\nZ\nd\nc\na'});
  3000. testVim('ex_sort_unique', function(cm, vim, helpers) {
  3001. helpers.doEx('sort u');
  3002. eq('Z\na\nb\nc\nd', cm.getValue());
  3003. }, { value: 'b\nZ\na\na\nd\na\nc\na'});
  3004. testVim('ex_sort_decimal', function(cm, vim, helpers) {
  3005. helpers.doEx('sort d');
  3006. eq('d3\n s5\n6\n.9', cm.getValue());
  3007. }, { value: '6\nd3\n s5\n.9'});
  3008. testVim('ex_sort_decimal_negative', function(cm, vim, helpers) {
  3009. helpers.doEx('sort d');
  3010. eq('z-9\nd3\n s5\n6\n.9', cm.getValue());
  3011. }, { value: '6\nd3\n s5\n.9\nz-9'});
  3012. testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) {
  3013. helpers.doEx('sort! d');
  3014. eq('.9\n6\n s5\nd3', cm.getValue());
  3015. }, { value: '6\nd3\n s5\n.9'});
  3016. testVim('ex_sort_hex', function(cm, vim, helpers) {
  3017. helpers.doEx('sort x');
  3018. eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue());
  3019. }, { value: '6\nd3\n s5\n&0xB\n.9'});
  3020. testVim('ex_sort_octal', function(cm, vim, helpers) {
  3021. helpers.doEx('sort o');
  3022. eq('.8\n.9\nd3\n s5\n6', cm.getValue());
  3023. }, { value: '6\nd3\n s5\n.9\n.8'});
  3024. testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) {
  3025. helpers.doEx('sort d');
  3026. eq('y\nz\nc1\nb2\na3', cm.getValue());
  3027. }, { value: 'a3\nz\nc1\ny\nb2'});
  3028. testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) {
  3029. helpers.doEx('sort! d');
  3030. eq('a3\nb2\nc1\nz\ny', cm.getValue());
  3031. }, { value: 'a3\nz\nc1\ny\nb2'});
  3032. // test for :global command
  3033. testVim('ex_global', function(cm, vim, helpers) {
  3034. cm.setCursor(0, 0);
  3035. helpers.doEx('g/one/s//two');
  3036. eq('two two\n two two\n two two', cm.getValue());
  3037. helpers.doEx('1,2g/two/s//one');
  3038. eq('one one\n one one\n two two', cm.getValue());
  3039. }, {value: 'one one\n one one\n one one'});
  3040. testVim('ex_global_confirm', function(cm, vim, helpers) {
  3041. cm.setCursor(0, 0);
  3042. var onKeyDown;
  3043. var openDialogSave = cm.openDialog;
  3044. var KEYCODES = {
  3045. a: 65,
  3046. n: 78,
  3047. q: 81,
  3048. y: 89
  3049. };
  3050. // Intercept the ex command, 'global'
  3051. cm.openDialog = function(template, callback, options) {
  3052. // Intercept the prompt for the embedded ex command, 'substitute'
  3053. cm.openDialog = function(template, callback, options) {
  3054. onKeyDown = options.onKeyDown;
  3055. };
  3056. callback('g/one/s//two/gc');
  3057. };
  3058. helpers.doKeys(':');
  3059. var close = function() {};
  3060. onKeyDown({keyCode: KEYCODES.n}, '', close);
  3061. onKeyDown({keyCode: KEYCODES.y}, '', close);
  3062. onKeyDown({keyCode: KEYCODES.a}, '', close);
  3063. onKeyDown({keyCode: KEYCODES.q}, '', close);
  3064. onKeyDown({keyCode: KEYCODES.y}, '', close);
  3065. eq('one two\n two two\n one one\n two one\n one one', cm.getValue());
  3066. }, {value: 'one one\n one one\n one one\n one one\n one one'});
  3067. // Basic substitute tests.
  3068. testVim('ex_substitute_same_line', function(cm, vim, helpers) {
  3069. cm.setCursor(1, 0);
  3070. helpers.doEx('s/one/two/g');
  3071. eq('one one\n two two', cm.getValue());
  3072. }, { value: 'one one\n one one'});
  3073. testVim('ex_substitute_full_file', function(cm, vim, helpers) {
  3074. cm.setCursor(1, 0);
  3075. helpers.doEx('%s/one/two/g');
  3076. eq('two two\n two two', cm.getValue());
  3077. }, { value: 'one one\n one one'});
  3078. testVim('ex_substitute_input_range', function(cm, vim, helpers) {
  3079. cm.setCursor(1, 0);
  3080. helpers.doEx('1,3s/\\d/0/g');
  3081. eq('0\n0\n0\n4', cm.getValue());
  3082. }, { value: '1\n2\n3\n4' });
  3083. testVim('ex_substitute_visual_range', function(cm, vim, helpers) {
  3084. cm.setCursor(1, 0);
  3085. // Set last visual mode selection marks '< and '> at lines 2 and 4
  3086. helpers.doKeys('V', '2', 'j', 'v');
  3087. helpers.doEx('\'<,\'>s/\\d/0/g');
  3088. eq('1\n0\n0\n0\n5', cm.getValue());
  3089. }, { value: '1\n2\n3\n4\n5' });
  3090. testVim('ex_substitute_empty_query', function(cm, vim, helpers) {
  3091. // If the query is empty, use last query.
  3092. cm.setCursor(1, 0);
  3093. cm.openDialog = helpers.fakeOpenDialog('1');
  3094. helpers.doKeys('/');
  3095. helpers.doEx('s//b/g');
  3096. eq('abb ab2 ab3', cm.getValue());
  3097. }, { value: 'a11 a12 a13' });
  3098. testVim('ex_substitute_javascript', function(cm, vim, helpers) {
  3099. CodeMirror.Vim.setOption('pcre', false);
  3100. cm.setCursor(1, 0);
  3101. // Throw all the things that javascript likes to treat as special values
  3102. // into the replace part. All should be literal (this is VIM).
  3103. helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g')
  3104. eq('a $$ $\' $` $& 0 b', cm.getValue());
  3105. }, { value: 'a 0 b' });
  3106. testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) {
  3107. cm.setCursor(0, 0);
  3108. helpers.doEx('s/a/b/g');
  3109. cm.setCursor(1, 0);
  3110. helpers.doEx('s');
  3111. eq('b b\nb a', cm.getValue());
  3112. }, {value: 'a a\na a'});
  3113. // More complex substitute tests that test both pcre and nopcre options.
  3114. function testSubstitute(name, options) {
  3115. testVim(name + '_pcre', function(cm, vim, helpers) {
  3116. cm.setCursor(1, 0);
  3117. CodeMirror.Vim.setOption('pcre', true);
  3118. helpers.doEx(options.expr);
  3119. eq(options.expectedValue, cm.getValue());
  3120. }, options);
  3121. // If no noPcreExpr is defined, assume that it's the same as the expr.
  3122. var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr;
  3123. testVim(name + '_nopcre', function(cm, vim, helpers) {
  3124. cm.setCursor(1, 0);
  3125. CodeMirror.Vim.setOption('pcre', false);
  3126. helpers.doEx(noPcreExpr);
  3127. eq(options.expectedValue, cm.getValue());
  3128. }, options);
  3129. }
  3130. testSubstitute('ex_substitute_capture', {
  3131. value: 'a11 a12 a13',
  3132. expectedValue: 'a1111 a1212 a1313',
  3133. // $n is a backreference
  3134. expr: 's/(\\d+)/$1$1/g',
  3135. // \n is a backreference.
  3136. noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'});
  3137. testSubstitute('ex_substitute_capture2', {
  3138. value: 'a 0 b',
  3139. expectedValue: 'a $00 b',
  3140. expr: 's/(\\d+)/$$$1$1/g',
  3141. noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'});
  3142. testSubstitute('ex_substitute_nocapture', {
  3143. value: 'a11 a12 a13',
  3144. expectedValue: 'a$1$1 a$1$1 a$1$1',
  3145. expr: 's/(\\d+)/$$1$$1/g',
  3146. noPcreExpr: 's/\\(\\d+\\)/$1$1/g'});
  3147. testSubstitute('ex_substitute_nocapture2', {
  3148. value: 'a 0 b',
  3149. expectedValue: 'a $10 b',
  3150. expr: 's/(\\d+)/$$1$1/g',
  3151. noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'});
  3152. testSubstitute('ex_substitute_nocapture', {
  3153. value: 'a b c',
  3154. expectedValue: 'a $ c',
  3155. expr: 's/b/$$/',
  3156. noPcreExpr: 's/b/$/'});
  3157. testSubstitute('ex_substitute_slash_regex', {
  3158. value: 'one/two \n three/four',
  3159. expectedValue: 'one|two \n three|four',
  3160. expr: '%s/\\//|'});
  3161. testSubstitute('ex_substitute_pipe_regex', {
  3162. value: 'one|two \n three|four',
  3163. expectedValue: 'one,two \n three,four',
  3164. expr: '%s/\\|/,/',
  3165. noPcreExpr: '%s/|/,/'});
  3166. testSubstitute('ex_substitute_or_regex', {
  3167. value: 'one|two \n three|four',
  3168. expectedValue: 'ana|twa \n thraa|faar',
  3169. expr: '%s/o|e|u/a/g',
  3170. noPcreExpr: '%s/o\\|e\\|u/a/g'});
  3171. testSubstitute('ex_substitute_or_word_regex', {
  3172. value: 'one|two \n three|four',
  3173. expectedValue: 'five|five \n three|four',
  3174. expr: '%s/(one|two)/five/g',
  3175. noPcreExpr: '%s/\\(one\\|two\\)/five/g'});
  3176. testSubstitute('ex_substitute_backslashslash_regex', {
  3177. value: 'one\\two \n three\\four',
  3178. expectedValue: 'one,two \n three,four',
  3179. expr: '%s/\\\\/,'});
  3180. testSubstitute('ex_substitute_slash_replacement', {
  3181. value: 'one,two \n three,four',
  3182. expectedValue: 'one/two \n three/four',
  3183. expr: '%s/,/\\/'});
  3184. testSubstitute('ex_substitute_backslash_replacement', {
  3185. value: 'one,two \n three,four',
  3186. expectedValue: 'one\\two \n three\\four',
  3187. expr: '%s/,/\\\\/g'});
  3188. testSubstitute('ex_substitute_multibackslash_replacement', {
  3189. value: 'one,two \n three,four',
  3190. expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes.
  3191. expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes.
  3192. testSubstitute('ex_substitute_braces_word', {
  3193. value: 'ababab abb ab{2}',
  3194. expectedValue: 'ab abb ab{2}',
  3195. expr: '%s/(ab){2}//g',
  3196. noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'});
  3197. testSubstitute('ex_substitute_braces_range', {
  3198. value: 'a aa aaa aaaa',
  3199. expectedValue: 'a a',
  3200. expr: '%s/a{2,3}//g',
  3201. noPcreExpr: '%s/a\\{2,3\\}//g'});
  3202. testSubstitute('ex_substitute_braces_literal', {
  3203. value: 'ababab abb ab{2}',
  3204. expectedValue: 'ababab abb ',
  3205. expr: '%s/ab\\{2\\}//g',
  3206. noPcreExpr: '%s/ab{2}//g'});
  3207. testSubstitute('ex_substitute_braces_char', {
  3208. value: 'ababab abb ab{2}',
  3209. expectedValue: 'ababab ab{2}',
  3210. expr: '%s/ab{2}//g',
  3211. noPcreExpr: '%s/ab\\{2\\}//g'});
  3212. testSubstitute('ex_substitute_braces_no_escape', {
  3213. value: 'ababab abb ab{2}',
  3214. expectedValue: 'ababab ab{2}',
  3215. expr: '%s/ab{2}//g',
  3216. noPcreExpr: '%s/ab\\{2}//g'});
  3217. testSubstitute('ex_substitute_count', {
  3218. value: '1\n2\n3\n4',
  3219. expectedValue: '1\n0\n0\n4',
  3220. expr: 's/\\d/0/i 2'});
  3221. testSubstitute('ex_substitute_count_with_range', {
  3222. value: '1\n2\n3\n4',
  3223. expectedValue: '1\n2\n0\n0',
  3224. expr: '1,3s/\\d/0/ 3'});
  3225. testSubstitute('ex_substitute_not_global', {
  3226. value: 'aaa\nbaa\ncaa',
  3227. expectedValue: 'xaa\nbxa\ncxa',
  3228. expr: '%s/a/x/'});
  3229. function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) {
  3230. testVim(name, function(cm, vim, helpers) {
  3231. var savedOpenDialog = cm.openDialog;
  3232. var savedKeyName = CodeMirror.keyName;
  3233. var onKeyDown;
  3234. var recordedCallback;
  3235. var closed = true; // Start out closed, set false on second openDialog.
  3236. function close() {
  3237. closed = true;
  3238. }
  3239. // First openDialog should save callback.
  3240. cm.openDialog = function(template, callback, options) {
  3241. recordedCallback = callback;
  3242. }
  3243. // Do first openDialog.
  3244. helpers.doKeys(':');
  3245. // Second openDialog should save keyDown handler.
  3246. cm.openDialog = function(template, callback, options) {
  3247. onKeyDown = options.onKeyDown;
  3248. closed = false;
  3249. };
  3250. // Return the command to Vim and trigger second openDialog.
  3251. recordedCallback(command);
  3252. // The event should really use keyCode, but here just mock it out and use
  3253. // key and replace keyName to just return key.
  3254. CodeMirror.keyName = function (e) { return e.key; }
  3255. keys = keys.toUpperCase();
  3256. for (var i = 0; i < keys.length; i++) {
  3257. is(!closed);
  3258. onKeyDown({ key: keys.charAt(i) }, '', close);
  3259. }
  3260. try {
  3261. eq(expectedValue, cm.getValue());
  3262. helpers.assertCursorAt(finalPos);
  3263. is(closed);
  3264. } catch(e) {
  3265. throw e
  3266. } finally {
  3267. // Restore overriden functions.
  3268. CodeMirror.keyName = savedKeyName;
  3269. cm.openDialog = savedOpenDialog;
  3270. }
  3271. }, { value: initialValue });
  3272. };
  3273. testSubstituteConfirm('ex_substitute_confirm_emptydoc',
  3274. '%s/x/b/c', '', '', '', makeCursor(0, 0));
  3275. testSubstituteConfirm('ex_substitute_confirm_nomatch',
  3276. '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0));
  3277. testSubstituteConfirm('ex_substitute_confirm_accept',
  3278. '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1));
  3279. testSubstituteConfirm('ex_substitute_confirm_random_keys',
  3280. '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1));
  3281. testSubstituteConfirm('ex_substitute_confirm_some',
  3282. '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1));
  3283. testSubstituteConfirm('ex_substitute_confirm_all',
  3284. '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1));
  3285. testSubstituteConfirm('ex_substitute_confirm_accept_then_all',
  3286. '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1));
  3287. testSubstituteConfirm('ex_substitute_confirm_quit',
  3288. '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3));
  3289. testSubstituteConfirm('ex_substitute_confirm_last',
  3290. '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
  3291. testSubstituteConfirm('ex_substitute_confirm_oneline',
  3292. '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3));
  3293. testSubstituteConfirm('ex_substitute_confirm_range_accept',
  3294. '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0));
  3295. testSubstituteConfirm('ex_substitute_confirm_range_some',
  3296. '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0));
  3297. testSubstituteConfirm('ex_substitute_confirm_range_all',
  3298. '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0));
  3299. testSubstituteConfirm('ex_substitute_confirm_range_last',
  3300. '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0));
  3301. //:noh should clear highlighting of search-results but allow to resume search through n
  3302. testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) {
  3303. cm.openDialog = helpers.fakeOpenDialog('match');
  3304. helpers.doKeys('?');
  3305. helpers.doEx('noh');
  3306. eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared');
  3307. helpers.doKeys('n');
  3308. helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting');
  3309. }, { value: 'match nope match \n nope Match' });
  3310. testVim('set_boolean', function(cm, vim, helpers) {
  3311. CodeMirror.Vim.defineOption('testoption', true, 'boolean');
  3312. // Test default value is set.
  3313. is(CodeMirror.Vim.getOption('testoption'));
  3314. try {
  3315. // Test fail to set to non-boolean
  3316. CodeMirror.Vim.setOption('testoption', '5');
  3317. fail();
  3318. } catch (expected) {};
  3319. // Test setOption
  3320. CodeMirror.Vim.setOption('testoption', false);
  3321. is(!CodeMirror.Vim.getOption('testoption'));
  3322. });
  3323. testVim('ex_set_boolean', function(cm, vim, helpers) {
  3324. CodeMirror.Vim.defineOption('testoption', true, 'boolean');
  3325. // Test default value is set.
  3326. is(CodeMirror.Vim.getOption('testoption'));
  3327. try {
  3328. // Test fail to set to non-boolean
  3329. helpers.doEx('set testoption=22');
  3330. fail();
  3331. } catch (expected) {};
  3332. // Test setOption
  3333. helpers.doEx('set notestoption');
  3334. is(!CodeMirror.Vim.getOption('testoption'));
  3335. });
  3336. testVim('set_string', function(cm, vim, helpers) {
  3337. CodeMirror.Vim.defineOption('testoption', 'a', 'string');
  3338. // Test default value is set.
  3339. eq('a', CodeMirror.Vim.getOption('testoption'));
  3340. try {
  3341. // Test fail to set non-string.
  3342. CodeMirror.Vim.setOption('testoption', true);
  3343. fail();
  3344. } catch (expected) {};
  3345. try {
  3346. // Test fail to set 'notestoption'
  3347. CodeMirror.Vim.setOption('notestoption', 'b');
  3348. fail();
  3349. } catch (expected) {};
  3350. // Test setOption
  3351. CodeMirror.Vim.setOption('testoption', 'c');
  3352. eq('c', CodeMirror.Vim.getOption('testoption'));
  3353. });
  3354. testVim('ex_set_string', function(cm, vim, helpers) {
  3355. CodeMirror.Vim.defineOption('testoption', 'a', 'string');
  3356. // Test default value is set.
  3357. eq('a', CodeMirror.Vim.getOption('testoption'));
  3358. try {
  3359. // Test fail to set 'notestoption'
  3360. helpers.doEx('set notestoption=b');
  3361. fail();
  3362. } catch (expected) {};
  3363. // Test setOption
  3364. helpers.doEx('set testoption=c')
  3365. eq('c', CodeMirror.Vim.getOption('testoption'));
  3366. });
  3367. // TODO: Reset key maps after each test.
  3368. testVim('ex_map_key2key', function(cm, vim, helpers) {
  3369. helpers.doEx('map a x');
  3370. helpers.doKeys('a');
  3371. helpers.assertCursorAt(0, 0);
  3372. eq('bc', cm.getValue());
  3373. }, { value: 'abc' });
  3374. testVim('ex_unmap_key2key', function(cm, vim, helpers) {
  3375. helpers.doEx('unmap a');
  3376. helpers.doKeys('a');
  3377. eq('vim-insert', cm.getOption('keyMap'));
  3378. }, { value: 'abc' });
  3379. testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) {
  3380. try {
  3381. helpers.doEx('unmap a');
  3382. fail();
  3383. } catch (expected) {}
  3384. helpers.doKeys('a');
  3385. eq('vim-insert', cm.getOption('keyMap'));
  3386. }, { value: 'abc' });
  3387. testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) {
  3388. helpers.doEx('map ; :');
  3389. var dialogOpened = false;
  3390. cm.openDialog = function() {
  3391. dialogOpened = true;
  3392. }
  3393. helpers.doKeys(';');
  3394. eq(dialogOpened, true);
  3395. });
  3396. testVim('ex_map_ex2key:', function(cm, vim, helpers) {
  3397. helpers.doEx('map :del x');
  3398. helpers.doEx('del');
  3399. helpers.assertCursorAt(0, 0);
  3400. eq('bc', cm.getValue());
  3401. }, { value: 'abc' });
  3402. testVim('ex_map_ex2ex', function(cm, vim, helpers) {
  3403. helpers.doEx('map :del :w');
  3404. var tmp = CodeMirror.commands.save;
  3405. var written = false;
  3406. var actualCm;
  3407. CodeMirror.commands.save = function(cm) {
  3408. written = true;
  3409. actualCm = cm;
  3410. };
  3411. helpers.doEx('del');
  3412. CodeMirror.commands.save = tmp;
  3413. eq(written, true);
  3414. eq(actualCm, cm);
  3415. });
  3416. testVim('ex_map_key2ex', function(cm, vim, helpers) {
  3417. helpers.doEx('map a :w');
  3418. var tmp = CodeMirror.commands.save;
  3419. var written = false;
  3420. var actualCm;
  3421. CodeMirror.commands.save = function(cm) {
  3422. written = true;
  3423. actualCm = cm;
  3424. };
  3425. helpers.doKeys('a');
  3426. CodeMirror.commands.save = tmp;
  3427. eq(written, true);
  3428. eq(actualCm, cm);
  3429. });
  3430. testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) {
  3431. CodeMirror.Vim.map('b', ':w', 'visual');
  3432. var tmp = CodeMirror.commands.save;
  3433. var written = false;
  3434. var actualCm;
  3435. CodeMirror.commands.save = function(cm) {
  3436. written = true;
  3437. actualCm = cm;
  3438. };
  3439. // Mapping should not work in normal mode.
  3440. helpers.doKeys('b');
  3441. eq(written, false);
  3442. // Mapping should work in visual mode.
  3443. helpers.doKeys('v', 'b');
  3444. eq(written, true);
  3445. eq(actualCm, cm);
  3446. CodeMirror.commands.save = tmp;
  3447. });
  3448. // Testing registration of functions as ex-commands and mapping to <Key>-keys
  3449. testVim('ex_api_test', function(cm, vim, helpers) {
  3450. var res=false;
  3451. var val='from';
  3452. CodeMirror.Vim.defineEx('extest','ext',function(cm,params){
  3453. if(params.args)val=params.args[0];
  3454. else res=true;
  3455. });
  3456. helpers.doEx(':ext to');
  3457. eq(val,'to','Defining ex-command failed');
  3458. CodeMirror.Vim.map('<C-CR><Space>',':ext');
  3459. helpers.doKeys('<C-CR>','<Space>');
  3460. is(res,'Mapping to key failed');
  3461. });
  3462. // For now, this test needs to be last because it messes up : for future tests.
  3463. testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) {
  3464. helpers.doEx('map : x');
  3465. helpers.doKeys(':');
  3466. helpers.assertCursorAt(0, 0);
  3467. eq('bc', cm.getValue());
  3468. }, { value: 'abc' });
  3469. // Test event handlers
  3470. testVim('beforeSelectionChange', function(cm, vim, helpers) {
  3471. cm.setCursor(0, 100);
  3472. eqPos(cm.getCursor('head'), cm.getCursor('anchor'));
  3473. }, { value: 'abc' });