vim_test.js 140 KB

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