jeygeethanmedia-inkpen 1.2.6.1

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