codemirror-rails 2.24 → 2.32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/.gitignore +1 -0
  2. data/Rakefile +19 -0
  3. data/codemirror-rails.gemspec +6 -1
  4. data/lib/codemirror/rails/version.rb +2 -2
  5. data/test/dummy/README.rdoc +261 -0
  6. data/test/dummy/Rakefile +7 -0
  7. data/test/dummy/app/assets/javascripts/application.js +15 -0
  8. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  9. data/test/dummy/app/controllers/application_controller.rb +3 -0
  10. data/test/dummy/app/helpers/application_helper.rb +2 -0
  11. data/test/dummy/app/mailers/.gitkeep +0 -0
  12. data/test/dummy/app/models/.gitkeep +0 -0
  13. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  14. data/test/dummy/config.ru +4 -0
  15. data/test/dummy/config/application.rb +56 -0
  16. data/test/dummy/config/boot.rb +10 -0
  17. data/test/dummy/config/environment.rb +5 -0
  18. data/test/dummy/config/environments/development.rb +37 -0
  19. data/test/dummy/config/environments/production.rb +67 -0
  20. data/test/dummy/config/environments/test.rb +37 -0
  21. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  22. data/test/dummy/config/initializers/inflections.rb +15 -0
  23. data/test/dummy/config/initializers/mime_types.rb +5 -0
  24. data/test/dummy/config/initializers/secret_token.rb +7 -0
  25. data/test/dummy/config/initializers/session_store.rb +8 -0
  26. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  27. data/test/dummy/config/locales/en.yml +5 -0
  28. data/test/dummy/config/routes.rb +58 -0
  29. data/test/dummy/lib/assets/.gitkeep +0 -0
  30. data/test/dummy/log/.gitkeep +0 -0
  31. data/test/dummy/public/404.html +26 -0
  32. data/test/dummy/public/422.html +26 -0
  33. data/test/dummy/public/500.html +25 -0
  34. data/test/dummy/public/favicon.ico +0 -0
  35. data/test/dummy/script/rails +6 -0
  36. data/test/integration/codemirror_rails_integration_test.rb +13 -0
  37. data/test/test_helper.rb +13 -0
  38. data/vendor/assets/javascripts/codemirror.js +381 -197
  39. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +1 -1
  40. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +649 -94
  41. data/vendor/assets/javascripts/codemirror/modes/clike.js +53 -7
  42. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +12 -7
  43. data/vendor/assets/javascripts/codemirror/modes/diff.js +24 -5
  44. data/vendor/assets/javascripts/codemirror/modes/ecl.js +2 -2
  45. data/vendor/assets/javascripts/codemirror/modes/erlang.js +463 -0
  46. data/vendor/assets/javascripts/codemirror/modes/gfm.js +38 -2
  47. data/vendor/assets/javascripts/codemirror/modes/go.js +1 -1
  48. data/vendor/assets/javascripts/codemirror/modes/groovy.js +1 -1
  49. data/vendor/assets/javascripts/codemirror/modes/haxe.js +432 -0
  50. data/vendor/assets/javascripts/codemirror/modes/javascript.js +1 -1
  51. data/vendor/assets/javascripts/codemirror/modes/less.js +93 -93
  52. data/vendor/assets/javascripts/codemirror/modes/markdown.js +29 -6
  53. data/vendor/assets/javascripts/codemirror/modes/mysql.js +6 -8
  54. data/vendor/assets/javascripts/codemirror/modes/ocaml.js +114 -0
  55. data/vendor/assets/javascripts/codemirror/modes/pascal.js +1 -1
  56. data/vendor/assets/javascripts/codemirror/modes/pig.js +2 -2
  57. data/vendor/assets/javascripts/codemirror/modes/plsql.js +2 -2
  58. data/vendor/assets/javascripts/codemirror/modes/python.js +13 -16
  59. data/vendor/assets/javascripts/codemirror/modes/ruby.js +3 -8
  60. data/vendor/assets/javascripts/codemirror/modes/scheme.js +74 -46
  61. data/vendor/assets/javascripts/codemirror/modes/shell.js +22 -7
  62. data/vendor/assets/javascripts/codemirror/modes/stex.js +7 -5
  63. data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +14 -14
  64. data/vendor/assets/javascripts/codemirror/modes/vb.js +260 -0
  65. data/vendor/assets/javascripts/codemirror/modes/verilog.js +1 -1
  66. data/vendor/assets/javascripts/codemirror/modes/xml.js +2 -1
  67. data/vendor/assets/javascripts/codemirror/modes/xquery.js +3 -3
  68. data/vendor/assets/javascripts/codemirror/utils/closetag.js +24 -34
  69. data/vendor/assets/javascripts/codemirror/utils/dialog.js +5 -1
  70. data/vendor/assets/javascripts/codemirror/utils/foldcode.js +10 -5
  71. data/vendor/assets/javascripts/codemirror/utils/formatting.js +8 -3
  72. data/vendor/assets/javascripts/codemirror/utils/loadmode.js +2 -1
  73. data/vendor/assets/javascripts/codemirror/utils/match-highlighter.js +1 -1
  74. data/vendor/assets/javascripts/codemirror/utils/multiplex.js +81 -0
  75. data/vendor/assets/javascripts/codemirror/utils/overlay.js +2 -1
  76. data/vendor/assets/javascripts/codemirror/utils/pig-hint.js +123 -0
  77. data/vendor/assets/javascripts/codemirror/utils/search.js +16 -12
  78. data/vendor/assets/javascripts/codemirror/utils/searchcursor.js +1 -1
  79. data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +4 -0
  80. data/vendor/assets/javascripts/codemirror/utils/xml-hint.js +137 -0
  81. data/vendor/assets/stylesheets/codemirror.css +59 -4
  82. data/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.css +14 -21
  83. data/vendor/assets/stylesheets/codemirror/themes/ambiance.css +1 -2
  84. data/vendor/assets/stylesheets/codemirror/themes/erlang-dark.css +21 -0
  85. data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +2 -3
  86. data/vendor/assets/stylesheets/codemirror/themes/night.css +1 -1
  87. data/vendor/assets/stylesheets/codemirror/themes/vibrant-ink.css +27 -0
  88. data/vendor/assets/stylesheets/codemirror/utils/dialog.css +4 -0
  89. metadata +98 -5
  90. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.css +0 -5
@@ -18,7 +18,7 @@
18
18
  "Alt-Y": function(cm) {cm.replaceSelection(popFromRing());},
19
19
  "Ctrl-/": "undo", "Shift-Ctrl--": "undo", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
20
20
  "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace",
21
- "Ctrl-Z": "undo", "Cmd-Z": "undo",
21
+ "Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete",
22
22
  fallthrough: ["basic", "emacsy"]
23
23
  };
24
24
 
@@ -1,21 +1,96 @@
1
+ // Supported keybindings:
2
+ //
3
+ // Cursor movement:
4
+ // h, j, k, l
5
+ // e, E, w, W, b, B
6
+ // Ctrl-f, Ctrl-b
7
+ // Ctrl-n, Ctrl-p
8
+ // $, ^, 0
9
+ // G
10
+ // ge, gE
11
+ // gg
12
+ // f<char>, F<char>, t<char>, T<char>
13
+ // Ctrl-o, Ctrl-i TODO (FIXME - Ctrl-O wont work in Chrome)
14
+ // /, ?, n, N TODO (does not work)
15
+ // #, * TODO
16
+ //
17
+ // Entering insert mode:
18
+ // i, I, a, A, o, O
19
+ // s
20
+ // ce, cb (without support for number of actions like c3e - TODO)
21
+ // cc
22
+ // S, C TODO
23
+ // cf<char>, cF<char>, ct<char>, cT<char>
24
+ //
25
+ // Deleting text:
26
+ // x, X
27
+ // J
28
+ // dd, D
29
+ // de, db (without support for number of actions like d3e - TODO)
30
+ // df<char>, dF<char>, dt<char>, dT<char>
31
+ //
32
+ // Yanking and pasting:
33
+ // yy, Y
34
+ // p, P
35
+ // p'<char> TODO - test
36
+ // y'<char> TODO - test
37
+ // m<char> TODO - test
38
+ //
39
+ // Changing text in place:
40
+ // ~
41
+ // r<char>
42
+ //
43
+ // Visual mode:
44
+ // v, V TODO
45
+ //
46
+ // Misc:
47
+ // . TODO
48
+ //
49
+
1
50
  (function() {
2
51
  var count = "";
3
52
  var sdir = "f";
4
53
  var buf = "";
5
54
  var yank = 0;
6
55
  var mark = [];
56
+ var reptTimes = 0;
7
57
  function emptyBuffer() { buf = ""; }
8
- function pushInBuffer(str) { buf += str; };
9
- function pushCountDigit(digit) { return function(cm) {count += digit;} }
10
- function popCount() { var i = parseInt(count); count = ""; return i || 1; }
58
+ function pushInBuffer(str) { buf += str; }
59
+ function pushCountDigit(digit) { return function(cm) {count += digit;}; }
60
+ function popCount() { var i = parseInt(count, 10); count = ""; return i || 1; }
61
+ function iterTimes(func) {
62
+ for (var i = 0, c = popCount(); i < c; ++i) func(i, i == c - 1);
63
+ }
11
64
  function countTimes(func) {
12
65
  if (typeof func == "string") func = CodeMirror.commands[func];
13
- return function(cm) { for (var i = 0, c = popCount(); i < c; ++i) func(cm); }
66
+ return function(cm) { iterTimes(function () { func(cm); }); };
14
67
  }
15
68
 
16
69
  function iterObj(o, f) {
17
70
  for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]);
18
71
  }
72
+ function iterList(l, f) {
73
+ for (var i in l) f(l[i]);
74
+ }
75
+ function toLetter(ch) {
76
+ // T -> t, Shift-T -> T, '*' -> *, "Space" -> " "
77
+ if (ch.slice(0, 6) == "Shift-") {
78
+ return ch.slice(0, 1);
79
+ } else {
80
+ if (ch == "Space") return " ";
81
+ if (ch.length == 3 && ch[0] == "'" && ch[2] == "'") return ch[1];
82
+ return ch.toLowerCase();
83
+ }
84
+ }
85
+ var SPECIAL_SYMBOLS = "~`!@#$%^&*()_-+=[{}]\\|/?.,<>:;\"\'1234567890";
86
+ function toCombo(ch) {
87
+ // t -> T, T -> Shift-T, * -> '*', " " -> "Space"
88
+ if (ch == " ") return "Space";
89
+ var specialIdx = SPECIAL_SYMBOLS.indexOf(ch);
90
+ if (specialIdx != -1) return "'" + ch + "'";
91
+ if (ch.toLowerCase() == ch) return ch.toUpperCase();
92
+ return "Shift-" + ch.toUpperCase();
93
+ }
19
94
 
20
95
  var word = [/\w/, /[^\w\s]/], bigWord = [/\S/];
21
96
  function findWord(line, pos, dir, regexps) {
@@ -37,42 +112,62 @@
37
112
  }
38
113
  return {from: Math.min(start, end), to: Math.max(start, end)};
39
114
  }
40
- function moveToWord(cm, regexps, dir, where) {
41
- var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line), word;
42
- while (true) {
43
- word = findWord(line, ch, dir, regexps);
44
- ch = word[where == "end" ? "to" : "from"];
45
- if (ch == cur.ch && word.from != word.to) ch = word[dir < 0 ? "from" : "to"];
46
- else break;
115
+ function moveToWord(cm, regexps, dir, times, where) {
116
+ var cur = cm.getCursor();
117
+
118
+ for (var i = 0; i < times; i++) {
119
+ var line = cm.getLine(cur.line), startCh = cur.ch, word;
120
+ while (true) {
121
+ // If we're at start/end of line, start on prev/next respectivly
122
+ if (cur.ch == line.length && dir > 0) {
123
+ cur.line++;
124
+ cur.ch = 0;
125
+ line = cm.getLine(cur.line);
126
+ } else if (cur.ch == 0 && dir < 0) {
127
+ cur.line--;
128
+ cur.ch = line.length;
129
+ line = cm.getLine(cur.line);
130
+ }
131
+ if (!line) break;
132
+
133
+ // On to the actual searching
134
+ word = findWord(line, cur.ch, dir, regexps);
135
+ cur.ch = word[where == "end" ? "to" : "from"];
136
+ if (startCh == cur.ch && word.from != word.to) cur.ch = word[dir < 0 ? "from" : "to"];
137
+ else break;
138
+ }
47
139
  }
48
- cm.setCursor(cur.line, word[where == "end" ? "to" : "from"], true);
140
+ return cur;
49
141
  }
50
142
  function joinLineNext(cm) {
51
143
  var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line);
52
- CodeMirror.commands.goLineEnd(cm);
144
+ CodeMirror.commands.goLineEnd(cm);
53
145
  if (cur.line != cm.lineCount()) {
54
146
  CodeMirror.commands.goLineEnd(cm);
55
147
  cm.replaceSelection(" ", "end");
56
148
  CodeMirror.commands.delCharRight(cm);
57
- }
58
- }
59
- function editCursor(mode) {
60
- if (mode == "vim-insert") {
61
- // put in your cursor css changing code
62
- } else if (mode == "vim") {
63
- // put in your cursor css changing code
64
149
  }
65
150
  }
66
- function delTillMark(cm, cHar) {
67
- var i = mark[cHar], l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
151
+ function delTillMark(cm, cHar) {
152
+ var i = mark[cHar];
153
+ if (i === undefined) {
154
+ // console.log("Mark not set"); // TODO - show in status bar
155
+ return;
156
+ }
157
+ var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
68
158
  cm.setCursor(start);
69
159
  for (var c = start; c <= end; c++) {
70
- pushInBuffer("\n"+cm.getLine(start));
160
+ pushInBuffer("\n"+cm.getLine(start));
71
161
  cm.removeLine(start);
72
162
  }
73
163
  }
74
- function yankTillMark(cm, cHar) {
75
- var i = mark[cHar], l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
164
+ function yankTillMark(cm, cHar) {
165
+ var i = mark[cHar];
166
+ if (i === undefined) {
167
+ // console.log("Mark not set"); // TODO - show in status bar
168
+ return;
169
+ }
170
+ var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
76
171
  for (var c = start; c <= end; c++) {
77
172
  pushInBuffer("\n"+cm.getLine(c));
78
173
  }
@@ -84,25 +179,104 @@
84
179
  cm.setCursor(cur.line, firstNonWS == -1 ? line.length : firstNonWS, true);
85
180
  }
86
181
 
182
+ function charIdxInLine(cm, cHar, motion_options) {
183
+ // Search for cHar in line.
184
+ // motion_options: {forward, inclusive}
185
+ // If inclusive = true, include it too.
186
+ // If forward = true, search forward, else search backwards.
187
+ // If char is not found on this line, do nothing
188
+ var cur = cm.getCursor(), line = cm.getLine(cur.line), idx;
189
+ var ch = toLetter(cHar), mo = motion_options;
190
+ if (mo.forward) {
191
+ idx = line.indexOf(ch, cur.ch + 1);
192
+ if (idx != -1 && mo.inclusive) idx += 1;
193
+ } else {
194
+ idx = line.lastIndexOf(ch, cur.ch);
195
+ if (idx != -1 && !mo.inclusive) idx += 1;
196
+ }
197
+ return idx;
198
+ }
199
+
200
+ function moveTillChar(cm, cHar, motion_options) {
201
+ // Move to cHar in line, as found by charIdxInLine.
202
+ var idx = charIdxInLine(cm, cHar, motion_options), cur = cm.getCursor();
203
+ if (idx != -1) cm.setCursor({line: cur.line, ch: idx});
204
+ }
205
+
206
+ function delTillChar(cm, cHar, motion_options) {
207
+ // delete text in this line, untill cHar is met,
208
+ // as found by charIdxInLine.
209
+ // If char is not found on this line, do nothing
210
+ var idx = charIdxInLine(cm, cHar, motion_options);
211
+ var cur = cm.getCursor();
212
+ if (idx !== -1) {
213
+ if (motion_options.forward) {
214
+ cm.replaceRange("", {line: cur.line, ch: cur.ch}, {line: cur.line, ch: idx});
215
+ } else {
216
+ cm.replaceRange("", {line: cur.line, ch: idx}, {line: cur.line, ch: cur.ch});
217
+ }
218
+ }
219
+ }
220
+
221
+ function enterInsertMode(cm) {
222
+ // enter insert mode: switch mode and cursor
223
+ popCount();
224
+ cm.setOption("keyMap", "vim-insert");
225
+ }
226
+
227
+ function dialog(cm, text, shortText, f) {
228
+ if (cm.openDialog) cm.openDialog(text, f);
229
+ else f(prompt(shortText, ""));
230
+ }
231
+ function showAlert(cm, text) {
232
+ if (cm.openDialog) cm.openDialog(CodeMirror.htmlEscape(text) + " <button type=button>OK</button>");
233
+ else alert(text);
234
+ }
235
+
236
+ // main keymap
87
237
  var map = CodeMirror.keyMap.vim = {
88
- "0": function(cm) {count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);},
89
238
  // Pipe (|); TODO: should be *screen* chars, so need a util function to turn tabs into spaces?
90
- "'|'": function(cm) {cm.setCursor(cm.getCursor().line, popCount() - 1, true);},
91
- "'^'": function(cm) {popCount(); goLineStartText(cm);},
92
- "A": function(cm) {popCount(); cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
93
- "Shift-A": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
94
- "I": function(cm) {popCount(); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
95
- "Shift-I": function(cm) {popCount(); goLineStartText(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
96
- "O": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); CodeMirror.commands.newlineAndIndent(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
97
- "Shift-O": function(cm) {popCount(); CodeMirror.commands.goLineStart(cm); cm.replaceSelection("\n", "start"); cm.indentLine(cm.getCursor().line); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
98
- "G": function(cm) {cm.setOption("keyMap", "vim-prefix-g");},
99
- "D": function(cm) {cm.setOption("keyMap", "vim-prefix-d"); emptyBuffer();},
239
+ "'|'": function(cm) {
240
+ cm.setCursor(cm.getCursor().line, popCount() - 1, true);
241
+ },
242
+ "A": function(cm) {
243
+ cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true);
244
+ enterInsertMode(cm);
245
+ },
246
+ "Shift-A": function(cm) { CodeMirror.commands.goLineEnd(cm); enterInsertMode(cm);},
247
+ "I": function(cm) { enterInsertMode(cm);},
248
+ "Shift-I": function(cm) { goLineStartText(cm); enterInsertMode(cm);},
249
+ "O": function(cm) {
250
+ CodeMirror.commands.goLineEnd(cm);
251
+ CodeMirror.commands.newlineAndIndent(cm);
252
+ enterInsertMode(cm);
253
+ },
254
+ "Shift-O": function(cm) {
255
+ CodeMirror.commands.goLineStart(cm);
256
+ cm.replaceSelection("\n", "start");
257
+ cm.indentLine(cm.getCursor().line);
258
+ enterInsertMode(cm);
259
+ },
260
+ "G": function(cm) { cm.setOption("keyMap", "vim-prefix-g");},
100
261
  "Shift-D": function(cm) {
262
+ // commented out verions works, but I left original, cause maybe
263
+ // I don't know vim enouth to see what it does
264
+ /* var cur = cm.getCursor();
265
+ var f = {line: cur.line, ch: cur.ch}, t = {line: cur.line};
266
+ pushInBuffer(cm.getRange(f, t));
267
+ */
101
268
  emptyBuffer();
102
269
  mark["Shift-D"] = cm.getCursor(false).line;
103
270
  cm.setCursor(cm.getCursor(true).line);
104
271
  delTillMark(cm,"Shift-D"); mark = [];
105
272
  },
273
+
274
+ "S": function (cm) {
275
+ countTimes(function (_cm) {
276
+ CodeMirror.commands.delCharRight(_cm);
277
+ })(cm);
278
+ enterInsertMode(cm);
279
+ },
106
280
  "M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark = [];},
107
281
  "Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer(); yank = 0;},
108
282
  "Shift-Y": function(cm) {
@@ -111,7 +285,7 @@
111
285
  cm.setCursor(cm.getCursor(true).line);
112
286
  yankTillMark(cm,"Shift-D"); mark = [];
113
287
  },
114
- "/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f"},
288
+ "/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f";},
115
289
  "'?'": function(cm) {
116
290
  var f = CodeMirror.commands.find;
117
291
  if (f) { f(cm); CodeMirror.commands.findPrev(cm); sdir = "r"; }
@@ -124,107 +298,488 @@
124
298
  var fn = CodeMirror.commands.findNext;
125
299
  if (fn) sdir != "r" ? CodeMirror.commands.findPrev(cm) : fn.findNext(cm);
126
300
  },
127
- "Shift-G": function(cm) {count == "" ? cm.setCursor(cm.lineCount()) : cm.setCursor(parseInt(count)-1); popCount(); CodeMirror.commands.goLineStart(cm);},
128
- nofallthrough: true
301
+ "Shift-G": function(cm) {
302
+ count == "" ? cm.setCursor(cm.lineCount()) : cm.setCursor(parseInt(count, 10)-1);
303
+ popCount();
304
+ CodeMirror.commands.goLineStart(cm);
305
+ },
306
+ "':'": function(cm) {
307
+ var exModeDialog = ': <input type="text" style="width: 90%"/>';
308
+ dialog(cm, exModeDialog, ':', function(command) {
309
+ if (command.match(/^\d+$/)) {
310
+ cm.setCursor(command - 1, cm.getCursor().ch);
311
+ } else {
312
+ showAlert(cm, "Bad command: " + command);
313
+ }
314
+ });
315
+ },
316
+ nofallthrough: true, style: "fat-cursor"
129
317
  };
130
- // Add bindings for number keys
131
- for (var i = 1; i < 10; ++i) map[i] = pushCountDigit(i);
318
+
319
+ // standard mode switching
320
+ iterList(["d", "t", "T", "f", "F", "c", "r"],
321
+ function (ch) {
322
+ CodeMirror.keyMap.vim[toCombo(ch)] = function (cm) {
323
+ cm.setOption("keyMap", "vim-prefix-" + ch);
324
+ emptyBuffer();
325
+ };
326
+ });
327
+
328
+ function addCountBindings(keyMap) {
329
+ // Add bindings for number keys
330
+ keyMap["0"] = function(cm) {
331
+ count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);
332
+ };
333
+ for (var i = 1; i < 10; ++i) keyMap[i] = pushCountDigit(i);
334
+ }
335
+ addCountBindings(CodeMirror.keyMap.vim);
336
+
337
+ // main num keymap
132
338
  // Add bindings that are influenced by number keys
133
339
  iterObj({
134
- "H": "goColumnLeft", "L": "goColumnRight", "J": "goLineDown",
135
- "K": "goLineUp", "Left": "goColumnLeft", "Right": "goColumnRight",
340
+ "Left": "goColumnLeft", "Right": "goColumnRight",
136
341
  "Down": "goLineDown", "Up": "goLineUp", "Backspace": "goCharLeft",
137
342
  "Space": "goCharRight",
138
- "B": function(cm) {moveToWord(cm, word, -1, "end");},
139
- "E": function(cm) {moveToWord(cm, word, 1, "end");},
140
- "W": function(cm) {moveToWord(cm, word, 1, "start");},
141
- "Shift-B": function(cm) {moveToWord(cm, bigWord, -1, "end");},
142
- "Shift-E": function(cm) {moveToWord(cm, bigWord, 1, "end");},
143
- "Shift-W": function(cm) {moveToWord(cm, bigWord, 1, "start");},
144
- "X": function(cm) {CodeMirror.commands.delCharRight(cm)},
343
+ "X": function(cm) {CodeMirror.commands.delCharRight(cm);},
145
344
  "P": function(cm) {
146
345
  var cur = cm.getCursor().line;
147
346
  if (buf!= "") {
148
- CodeMirror.commands.goLineEnd(cm);
347
+ if (buf[0] == "\n") CodeMirror.commands.goLineEnd(cm);
348
+ cm.replaceRange(buf, cm.getCursor());
349
+ }
350
+ },
351
+ "Shift-X": function(cm) {CodeMirror.commands.delCharLeft(cm);},
352
+ "Shift-J": function(cm) {joinLineNext(cm);},
353
+ "Shift-P": function(cm) {
354
+ var cur = cm.getCursor().line;
355
+ if (buf!= "") {
356
+ CodeMirror.commands.goLineUp(cm);
357
+ CodeMirror.commands.goLineEnd(cm);
149
358
  cm.replaceSelection(buf, "end");
150
359
  }
151
360
  cm.setCursor(cur+1);
152
361
  },
153
- "Shift-X": function(cm) {CodeMirror.commands.delCharLeft(cm)},
154
- "Shift-J": function(cm) {joinLineNext(cm)},
155
362
  "'~'": function(cm) {
156
363
  var cur = cm.getCursor(), cHar = cm.getRange({line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
157
364
  cHar = cHar != cHar.toLowerCase() ? cHar.toLowerCase() : cHar.toUpperCase();
158
365
  cm.replaceRange(cHar, {line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
159
366
  cm.setCursor(cur.line, cur.ch+1);
160
367
  },
161
- "Ctrl-B": function(cm) {CodeMirror.commands.goPageUp(cm)},
162
- "Ctrl-F": function(cm) {CodeMirror.commands.goPageDown(cm)},
368
+ "Ctrl-B": function(cm) {CodeMirror.commands.goPageUp(cm);},
369
+ "Ctrl-F": function(cm) {CodeMirror.commands.goPageDown(cm);},
163
370
  "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
164
- "U": "undo", "Ctrl-R": "redo", "'$'": "goLineEnd"
165
- }, function(key, cmd) { map[key] = countTimes(cmd); });
371
+ "U": "undo", "Ctrl-R": "redo"
372
+ }, function(key, cmd) { map[key] = countTimes(cmd); });
373
+
374
+ // empty key maps
375
+ iterList([
376
+ "vim-prefix-d'",
377
+ "vim-prefix-y'",
378
+ "vim-prefix-df",
379
+ "vim-prefix-dF",
380
+ "vim-prefix-dt",
381
+ "vim-prefix-dT",
382
+ "vim-prefix-c",
383
+ "vim-prefix-cf",
384
+ "vim-prefix-cF",
385
+ "vim-prefix-ct",
386
+ "vim-prefix-cT",
387
+ "vim-prefix-",
388
+ "vim-prefix-f",
389
+ "vim-prefix-F",
390
+ "vim-prefix-t",
391
+ "vim-prefix-T",
392
+ "vim-prefix-r",
393
+ "vim-prefix-m"
394
+ ],
395
+ function (prefix) {
396
+ CodeMirror.keyMap[prefix] = {
397
+ auto: "vim",
398
+ nofallthrough: true,
399
+ style: "fat-cursor"
400
+ };
401
+ });
166
402
 
167
403
  CodeMirror.keyMap["vim-prefix-g"] = {
168
- "E": countTimes(function(cm) { moveToWord(cm, word, -1, "start");}),
169
- "Shift-E": countTimes(function(cm) { moveToWord(cm, bigWord, -1, "start");}),
170
- auto: "vim",
171
- nofallthrough: true
404
+ "E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, word, -1, 1, "start"));}),
405
+ "Shift-E": countTimes(function(cm) { cm.setCursor(moveToWord(cm, bigWord, -1, 1, "start"));}),
406
+ "G": function (cm) { cm.setCursor({line: 0, ch: cm.getCursor().ch});},
407
+ auto: "vim", nofallthrough: true, style: "fat-cursor"
172
408
  };
173
409
 
174
- CodeMirror.keyMap["vim-prefix-m"] = {
175
- auto: "vim",
176
- nofallthrough: true
177
- };
178
-
179
410
  CodeMirror.keyMap["vim-prefix-d"] = {
180
- "D": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line)); cm.removeLine(cm.getCursor().line); }),
181
- "'": function(cm) {cm.setOption("keyMap", "vim-prefix-d'"); emptyBuffer();},
182
- auto: "vim",
183
- nofallthrough: true
411
+ "D": countTimes(function(cm) {
412
+ pushInBuffer("\n"+cm.getLine(cm.getCursor().line));
413
+ cm.removeLine(cm.getCursor().line);
414
+ cm.setOption("keyMap", "vim");
415
+ }),
416
+ "'": function(cm) {
417
+ cm.setOption("keyMap", "vim-prefix-d'");
418
+ emptyBuffer();
419
+ },
420
+ "B": function(cm) {
421
+ var cur = cm.getCursor();
422
+ var line = cm.getLine(cur.line);
423
+ var index = line.lastIndexOf(" ", cur.ch);
424
+
425
+ pushInBuffer(line.substring(index, cur.ch));
426
+ cm.replaceRange("", {line: cur.line, ch: index}, cur);
427
+ cm.setOption("keyMap", "vim");
428
+ },
429
+ nofallthrough: true, style: "fat-cursor"
184
430
  };
431
+ // FIXME - does not work for bindings like "d3e"
432
+ addCountBindings(CodeMirror.keyMap["vim-prefix-d"]);
185
433
 
186
- CodeMirror.keyMap["vim-prefix-d'"] = {
187
- auto: "vim",
188
- nofallthrough: true
434
+ CodeMirror.keyMap["vim-prefix-c"] = {
435
+ "B": function (cm) {
436
+ countTimes("delWordLeft")(cm);
437
+ enterInsertMode(cm);
438
+ },
439
+ "C": function (cm) {
440
+ iterTimes(function (i, last) {
441
+ CodeMirror.commands.deleteLine(cm);
442
+ if (i) {
443
+ CodeMirror.commands.delCharRight(cm);
444
+ if (last) CodeMirror.commands.deleteLine(cm);
445
+ }
446
+ });
447
+ enterInsertMode(cm);
448
+ },
449
+ nofallthrough: true, style: "fat-cursor"
189
450
  };
190
451
 
191
- CodeMirror.keyMap["vim-prefix-y'"] = {
192
- auto: "vim",
193
- nofallthrough: true
452
+ iterList(["vim-prefix-d", "vim-prefix-c", "vim-prefix-"], function (prefix) {
453
+ iterList(["f", "F", "T", "t"],
454
+ function (ch) {
455
+ CodeMirror.keyMap[prefix][toCombo(ch)] = function (cm) {
456
+ cm.setOption("keyMap", prefix + ch);
457
+ emptyBuffer();
458
+ };
459
+ });
460
+ });
461
+
462
+ var MOTION_OPTIONS = {
463
+ "t": {inclusive: false, forward: true},
464
+ "f": {inclusive: true, forward: true},
465
+ "T": {inclusive: false, forward: false},
466
+ "F": {inclusive: true, forward: false}
194
467
  };
195
468
 
196
- // iterate through uppercase alphabet char codes
197
- for (var i = 65; i < 65 + 26; i++) {
198
- // apply for `letter` and 'Shift-' + `letter`
199
- for (var m = String.fromCharCode(i); m.length < 8; m = "Shift-" + m) {
200
- CodeMirror.keyMap["vim-prefix-m"][m] = function(cm) {
201
- mark[m] = cm.getCursor().line;
469
+ function setupPrefixBindingForKey(m) {
470
+ CodeMirror.keyMap["vim-prefix-m"][m] = function(cm) {
471
+ mark[m] = cm.getCursor().line;
472
+ };
473
+ CodeMirror.keyMap["vim-prefix-d'"][m] = function(cm) {
474
+ delTillMark(cm,m);
475
+ };
476
+ CodeMirror.keyMap["vim-prefix-y'"][m] = function(cm) {
477
+ yankTillMark(cm,m);
478
+ };
479
+ CodeMirror.keyMap["vim-prefix-r"][m] = function (cm) {
480
+ var cur = cm.getCursor();
481
+ cm.replaceRange(toLetter(m),
482
+ {line: cur.line, ch: cur.ch},
483
+ {line: cur.line, ch: cur.ch + 1});
484
+ CodeMirror.commands.goColumnLeft(cm);
485
+ };
486
+ // all commands, related to motions till char in line
487
+ iterObj(MOTION_OPTIONS, function (ch, options) {
488
+ CodeMirror.keyMap["vim-prefix-" + ch][m] = function(cm) {
489
+ moveTillChar(cm, m, options);
202
490
  };
203
- CodeMirror.keyMap["vim-prefix-d'"][m] = function(cm) {
204
- delTillMark(cm,m);
491
+ CodeMirror.keyMap["vim-prefix-d" + ch][m] = function(cm) {
492
+ delTillChar(cm, m, options);
205
493
  };
206
- CodeMirror.keyMap["vim-prefix-y'"][m] = function(cm) {
207
- yankTillMark(cm,m);
494
+ CodeMirror.keyMap["vim-prefix-c" + ch][m] = function(cm) {
495
+ delTillChar(cm, m, options);
496
+ enterInsertMode(cm);
208
497
  };
209
- }
498
+ });
210
499
  }
500
+ for (var i = 65; i < 65 + 26; i++) { // uppercase alphabet char codes
501
+ var ch = String.fromCharCode(i);
502
+ setupPrefixBindingForKey(toCombo(ch));
503
+ setupPrefixBindingForKey(toCombo(ch.toLowerCase()));
504
+ }
505
+ iterList(SPECIAL_SYMBOLS, function (ch) {
506
+ setupPrefixBindingForKey(toCombo(ch));
507
+ });
508
+ setupPrefixBindingForKey("Space");
211
509
 
212
510
  CodeMirror.keyMap["vim-prefix-y"] = {
213
511
  "Y": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line+yank)); yank++; }),
214
512
  "'": function(cm) {cm.setOption("keyMap", "vim-prefix-y'"); emptyBuffer();},
215
- auto: "vim",
216
- nofallthrough: true
513
+ nofallthrough: true, style: "fat-cursor"
217
514
  };
218
515
 
219
516
  CodeMirror.keyMap["vim-insert"] = {
220
517
  // TODO: override navigation keys so that Esc will cancel automatic indentation from o, O, i_<CR>
221
518
  "Esc": function(cm) {
222
- cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
519
+ cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
223
520
  cm.setOption("keyMap", "vim");
224
- editCursor("vim");
225
- },
226
- "Ctrl-N": function(cm) {/* Code to bring up autocomplete hint */},
227
- "Ctrl-P": function(cm) {/* Code to bring up autocomplete hint */},
521
+ },
522
+ "Ctrl-N": "autocomplete",
523
+ "Ctrl-P": "autocomplete",
228
524
  fallthrough: ["default"]
229
525
  };
526
+
527
+ function findMatchedSymbol(cm, cur, symb) {
528
+ var line = cur.line;
529
+ var symb = symb ? symb : cm.getLine(line)[cur.ch];
530
+
531
+ // Are we at the opening or closing char
532
+ var forwards = ['(', '[', '{'].indexOf(symb) != -1;
533
+
534
+ var reverseSymb = (function(sym) {
535
+ switch (sym) {
536
+ case '(' : return ')';
537
+ case '[' : return ']';
538
+ case '{' : return '}';
539
+ case ')' : return '(';
540
+ case ']' : return '[';
541
+ case '}' : return '{';
542
+ default : return null;
543
+ }
544
+ })(symb);
545
+
546
+ // Couldn't find a matching symbol, abort
547
+ if (reverseSymb == null) return cur;
548
+
549
+ // Tracking our imbalance in open/closing symbols. An opening symbol wii be
550
+ // the first thing we pick up if moving forward, this isn't true moving backwards
551
+ var disBal = forwards ? 0 : 1;
552
+
553
+ while (true) {
554
+ if (line == cur.line) {
555
+ // First pass, do some special stuff
556
+ var currLine = forwards ? cm.getLine(line).substr(cur.ch).split('') : cm.getLine(line).substr(0,cur.ch).split('').reverse();
557
+ } else {
558
+ var currLine = forwards ? cm.getLine(line).split('') : cm.getLine(line).split('').reverse();
559
+ }
560
+
561
+ for (var index = 0; index < currLine.length; index++) {
562
+ if (currLine[index] == symb) disBal++;
563
+ else if (currLine[index] == reverseSymb) disBal--;
564
+
565
+ if (disBal == 0) {
566
+ if (forwards && cur.line == line) return {line: line, ch: index + cur.ch};
567
+ else if (forwards) return {line: line, ch: index};
568
+ else return {line: line, ch: currLine.length - index - 1 };
569
+ }
570
+ }
571
+
572
+ if (forwards) line++;
573
+ else line--;
574
+ }
575
+ }
576
+
577
+ function selectCompanionObject(cm, revSymb, inclusive) {
578
+ var cur = cm.getCursor();
579
+
580
+ var end = findMatchedSymbol(cm, cur, revSymb);
581
+ var start = findMatchedSymbol(cm, end);
582
+ start.ch += inclusive ? 1 : 0;
583
+ end.ch += inclusive ? 0 : 1;
584
+
585
+ return {start: start, end: end};
586
+ }
587
+
588
+ // These are our motion commands to be used for navigation and selection with
589
+ // certian other commands. All should return a cursor object.
590
+ var motionList = ['B', 'E', 'J', 'K', 'H', 'L', 'W', 'Shift-W', "'^'", "'$'", "'%'", 'Esc'];
591
+
592
+ motions = {
593
+ 'B': function(cm, times) { return moveToWord(cm, word, -1, times); },
594
+ 'Shift-B': function(cm, times) { return moveToWord(cm, bigWord, -1, times); },
595
+ 'E': function(cm, times) { return moveToWord(cm, word, 1, times, 'end'); },
596
+ 'Shift-E': function(cm, times) { return moveToWord(cm, bigWord, 1, times, 'end'); },
597
+ 'J': function(cm, times) {
598
+ var cur = cm.getCursor();
599
+ return {line: cur.line+times, ch : cur.ch};
600
+ },
601
+
602
+ 'K': function(cm, times) {
603
+ var cur = cm.getCursor();
604
+ return {line: cur.line-times, ch: cur.ch};
605
+ },
606
+
607
+ 'H': function(cm, times) {
608
+ var cur = cm.getCursor();
609
+ return {line: cur.line, ch: cur.ch-times};
610
+ },
611
+
612
+ 'L': function(cm, times) {
613
+ var cur = cm.getCursor();
614
+ return {line: cur.line, ch: cur.ch+times};
615
+ },
616
+ 'W': function(cm, times) { return moveToWord(cm, word, 1, times); },
617
+ 'Shift-W': function(cm, times) { return moveToWord(cm, bigWord, 1, times); },
618
+ "'^'": function(cm, times) {
619
+ var cur = cm.getCursor();
620
+ var line = cm.getLine(cur.line).split('');
621
+
622
+ // Empty line :o
623
+ if (line.length == 0) return cur;
624
+
625
+ for (var index = 0; index < line.length; index++) {
626
+ if (line[index].match(/[^\s]/)) return {line: cur.line, ch: index};
627
+ }
628
+ },
629
+ "'$'": function(cm) {
630
+ var cur = cm.getCursor();
631
+ var line = cm.getLine(cur.line);
632
+ return {line: cur.line, ch: line.length};
633
+ },
634
+ "'%'": function(cm) { return findMatchedSymbol(cm, cm.getCursor()); },
635
+ "Esc" : function(cm) {
636
+ cm.setOption('vim');
637
+ reptTimes = 0;
638
+
639
+ return cm.getCursor();
640
+ }
641
+ };
642
+
643
+ // Map our movement actions each operator and non-operational movement
644
+ motionList.forEach(function(key, index, array) {
645
+ CodeMirror.keyMap['vim-prefix-d'][key] = function(cm) {
646
+ // Get our selected range
647
+ var start = cm.getCursor();
648
+ var end = motions[key](cm, reptTimes ? reptTimes : 1);
649
+
650
+ // Set swap var if range is of negative length
651
+ if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
652
+
653
+ // Take action, switching start and end if swap var is set
654
+ pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
655
+ cm.replaceRange("", swap ? end : start, swap ? start : end);
656
+
657
+ // And clean up
658
+ reptTimes = 0;
659
+ cm.setOption("keyMap", "vim");
660
+ };
661
+
662
+ CodeMirror.keyMap['vim-prefix-c'][key] = function(cm) {
663
+ var start = cm.getCursor();
664
+ var end = motions[key](cm, reptTimes ? reptTimes : 1);
665
+
666
+ if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
667
+ pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
668
+ cm.replaceRange("", swap ? end : start, swap ? start : end);
669
+
670
+ reptTimes = 0;
671
+ cm.setOption('keyMap', 'vim-insert');
672
+ };
673
+
674
+ CodeMirror.keyMap['vim-prefix-y'][key] = function(cm) {
675
+ var start = cm.getCursor();
676
+ var end = motions[key](cm, reptTimes ? reptTimes : 1);
677
+
678
+ if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true;
679
+ pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
680
+
681
+ reptTimes = 0;
682
+ cm.setOption("keyMap", "vim");
683
+ };
684
+
685
+ CodeMirror.keyMap['vim'][key] = function(cm) {
686
+ var cur = motions[key](cm, reptTimes ? reptTimes : 1);
687
+ cm.setCursor(cur.line, cur.ch);
688
+
689
+ reptTimes = 0;
690
+ };
691
+ });
692
+
693
+ var nums = [1,2,3,4,5,6,7,8,9];
694
+ nums.forEach(function(key, index, array) {
695
+ CodeMirror.keyMap['vim'][key] = function (cm) {
696
+ reptTimes = (reptTimes * 10) + key;
697
+ };
698
+ CodeMirror.keyMap['vim-prefix-d'][key] = function (cm) {
699
+ reptTimes = (reptTimes * 10) + key;
700
+ };
701
+ CodeMirror.keyMap['vim-prefix-y'][key] = function (cm) {
702
+ reptTimes = (reptTimes * 10) + key;
703
+ };
704
+ CodeMirror.keyMap['vim-prefix-c'][key] = function (cm) {
705
+ reptTimes = (reptTimes * 10) + key;
706
+ };
707
+ });
708
+
709
+ // Create our keymaps for each operator and make xa and xi where x is an operator
710
+ // change to the corrosponding keymap
711
+ var operators = ['d', 'y', 'c'];
712
+ operators.forEach(function(key, index, array) {
713
+ CodeMirror.keyMap['vim-prefix-'+key+'a'] = {
714
+ auto: 'vim', nofallthrough: true, style: "fat-cursor"
715
+ };
716
+ CodeMirror.keyMap['vim-prefix-'+key+'i'] = {
717
+ auto: 'vim', nofallthrough: true, style: "fat-cursor"
718
+ };
719
+
720
+ CodeMirror.keyMap['vim-prefix-'+key]['A'] = function(cm) {
721
+ reptTimes = 0;
722
+ cm.setOption('keyMap', 'vim-prefix-' + key + 'a');
723
+ };
724
+
725
+ CodeMirror.keyMap['vim-prefix-'+key]['I'] = function(cm) {
726
+ reptTimes = 0;
727
+ cm.setOption('keyMap', 'vim-prefix-' + key + 'i');
728
+ };
729
+ });
730
+
731
+ function regexLastIndexOf(string, pattern, startIndex) {
732
+ for (var i = startIndex == null ? string.length : startIndex; i >= 0; --i)
733
+ if (pattern.test(string.charAt(i))) return i;
734
+ return -1;
735
+ }
736
+
737
+ // Create our text object functions. They work similar to motions but they
738
+ // return a start cursor as well
739
+ var textObjectList = ['W', 'Shift-[', 'Shift-9', '['];
740
+ var textObjects = {
741
+ 'W': function(cm, inclusive) {
742
+ var cur = cm.getCursor();
743
+ var line = cm.getLine(cur.line);
744
+
745
+ var line_to_char = new String(line.substring(0, cur.ch));
746
+ var start = regexLastIndexOf(line_to_char, /[^a-zA-Z0-9]/) + 1;
747
+ var end = motions["E"](cm, 1) ;
748
+
749
+ end.ch += inclusive ? 1 : 0 ;
750
+ return {start: {line: cur.line, ch: start}, end: end };
751
+ },
752
+ 'Shift-[': function(cm, inclusive) { return selectCompanionObject(cm, '}', inclusive); },
753
+ 'Shift-9': function(cm, inclusive) { return selectCompanionObject(cm, ')', inclusive); },
754
+ '[': function(cm, inclusive) { return selectCompanionObject(cm, ']', inclusive); }
755
+ };
756
+
757
+ // One function to handle all operation upon text objects. Kinda funky but it works
758
+ // better than rewriting this code six times
759
+ function textObjectManipulation(cm, object, remove, insert, inclusive) {
760
+ // Object is the text object, delete object if remove is true, enter insert
761
+ // mode if insert is true, inclusive is the difference between a and i
762
+ var tmp = textObjects[object](cm, inclusive);
763
+ var start = tmp.start;
764
+ var end = tmp.end;
765
+
766
+ if ((start.line > end.line) || (start.line == end.line && start.ch > end.ch)) var swap = true ;
767
+
768
+ pushInBuffer(cm.getRange(swap ? end : start, swap ? start : end));
769
+ if (remove) cm.replaceRange("", swap ? end : start, swap ? start : end);
770
+ if (insert) cm.setOption('keyMap', 'vim-insert');
771
+ }
772
+
773
+ // And finally build the keymaps up from the text objects
774
+ for (var i = 0; i < textObjectList.length; ++i) {
775
+ var object = textObjectList[i];
776
+ (function(object) {
777
+ CodeMirror.keyMap['vim-prefix-di'][object] = function(cm) { textObjectManipulation(cm, object, true, false, false); };
778
+ CodeMirror.keyMap['vim-prefix-da'][object] = function(cm) { textObjectManipulation(cm, object, true, false, true); };
779
+ CodeMirror.keyMap['vim-prefix-yi'][object] = function(cm) { textObjectManipulation(cm, object, false, false, false); };
780
+ CodeMirror.keyMap['vim-prefix-ya'][object] = function(cm) { textObjectManipulation(cm, object, false, false, true); };
781
+ CodeMirror.keyMap['vim-prefix-ci'][object] = function(cm) { textObjectManipulation(cm, object, true, true, false); };
782
+ CodeMirror.keyMap['vim-prefix-ca'][object] = function(cm) { textObjectManipulation(cm, object, true, true, true); };
783
+ })(object)
784
+ }
230
785
  })();