codemirror-rails 3.20 → 3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +240 -135
  4. data/vendor/assets/javascripts/codemirror/addons/comment/comment.js +6 -2
  5. data/vendor/assets/javascripts/codemirror/addons/comment/continuecomment.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +1 -0
  7. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +5 -3
  8. data/vendor/assets/javascripts/codemirror/addons/edit/closetag.js +10 -6
  9. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +2 -0
  10. data/vendor/assets/javascripts/codemirror/addons/edit/matchbrackets.js +1 -1
  11. data/vendor/assets/javascripts/codemirror/addons/fold/comment-fold.js +3 -1
  12. data/vendor/assets/javascripts/codemirror/addons/fold/foldcode.js +13 -2
  13. data/vendor/assets/javascripts/codemirror/addons/fold/foldgutter.js +1 -1
  14. data/vendor/assets/javascripts/codemirror/addons/fold/indent-fold.js +2 -2
  15. data/vendor/assets/javascripts/codemirror/addons/fold/xml-fold.js +6 -0
  16. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +3 -5
  17. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +29 -33
  18. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/addons/hint/pig-hint.js +1 -1
  20. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +1 -5
  21. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +58 -9
  22. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +58 -17
  23. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +5 -5
  24. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +1 -1
  25. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +6 -1
  26. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex.js +5 -3
  27. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode-standalone.js +26 -11
  28. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.js +1 -1
  29. data/vendor/assets/javascripts/codemirror/addons/runmode/runmode.node.js +22 -11
  30. data/vendor/assets/javascripts/codemirror/addons/search/search.js +22 -9
  31. data/vendor/assets/javascripts/codemirror/addons/search/searchcursor.js +48 -24
  32. data/vendor/assets/javascripts/codemirror/addons/selection/active-line.js +15 -9
  33. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +3 -3
  34. data/vendor/assets/javascripts/codemirror/addons/wrap/hardwrap.js +21 -9
  35. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +12 -1
  36. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +110 -28
  37. data/vendor/assets/javascripts/codemirror/modes/clike.js +28 -9
  38. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +3 -4
  39. data/vendor/assets/javascripts/codemirror/modes/css.js +341 -297
  40. data/vendor/assets/javascripts/codemirror/modes/erlang.js +302 -179
  41. data/vendor/assets/javascripts/codemirror/modes/gfm.js +10 -5
  42. data/vendor/assets/javascripts/codemirror/modes/gherkin.js +45 -50
  43. data/vendor/assets/javascripts/codemirror/modes/haml.js +0 -4
  44. data/vendor/assets/javascripts/codemirror/modes/haskell.js +5 -3
  45. data/vendor/assets/javascripts/codemirror/modes/htmlembedded.js +0 -2
  46. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +0 -2
  47. data/vendor/assets/javascripts/codemirror/modes/javascript.js +43 -30
  48. data/vendor/assets/javascripts/codemirror/modes/jinja2.js +13 -3
  49. data/vendor/assets/javascripts/codemirror/modes/less.js +7 -6
  50. data/vendor/assets/javascripts/codemirror/modes/markdown.js +231 -45
  51. data/vendor/assets/javascripts/codemirror/modes/{ocaml.js → mllike.js} +88 -13
  52. data/vendor/assets/javascripts/codemirror/modes/pegjs.js +5 -9
  53. data/vendor/assets/javascripts/codemirror/modes/php.js +6 -7
  54. data/vendor/assets/javascripts/codemirror/modes/python.js +6 -0
  55. data/vendor/assets/javascripts/codemirror/modes/r.js +5 -1
  56. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.js +1 -1
  57. data/vendor/assets/javascripts/codemirror/modes/ruby.js +3 -1
  58. data/vendor/assets/javascripts/codemirror/modes/smalltalk.js +4 -2
  59. data/vendor/assets/javascripts/codemirror/modes/smartymixed.js +0 -2
  60. data/vendor/assets/javascripts/codemirror/modes/sql.js +5 -4
  61. data/vendor/assets/javascripts/codemirror/modes/xml.js +87 -100
  62. data/vendor/assets/stylesheets/codemirror/themes/mbo.css +1 -1
  63. data/vendor/assets/stylesheets/codemirror/themes/midnight.css +1 -1
  64. data/vendor/assets/stylesheets/codemirror/themes/pastel-on-dark.css +49 -0
  65. data/vendor/assets/stylesheets/codemirror/themes/the-matrix.css +1 -1
  66. metadata +3 -2
@@ -12,10 +12,10 @@
12
12
  CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
13
13
  var prev = old && old != CodeMirror.Init;
14
14
  if (val && !prev) {
15
- updateActiveLine(cm);
16
- cm.on("cursorActivity", updateActiveLine);
15
+ updateActiveLine(cm, cm.getCursor().line);
16
+ cm.on("beforeSelectionChange", selectionChange);
17
17
  } else if (!val && prev) {
18
- cm.off("cursorActivity", updateActiveLine);
18
+ cm.off("beforeSelectionChange", selectionChange);
19
19
  clearActiveLine(cm);
20
20
  delete cm.state.activeLine;
21
21
  }
@@ -28,12 +28,18 @@
28
28
  }
29
29
  }
30
30
 
31
- function updateActiveLine(cm) {
32
- var line = cm.getLineHandleVisualStart(cm.getCursor().line);
31
+ function updateActiveLine(cm, selectedLine) {
32
+ var line = cm.getLineHandleVisualStart(selectedLine);
33
33
  if (cm.state.activeLine == line) return;
34
- clearActiveLine(cm);
35
- cm.addLineClass(line, "wrap", WRAP_CLASS);
36
- cm.addLineClass(line, "background", BACK_CLASS);
37
- cm.state.activeLine = line;
34
+ cm.operation(function() {
35
+ clearActiveLine(cm);
36
+ cm.addLineClass(line, "wrap", WRAP_CLASS);
37
+ cm.addLineClass(line, "background", BACK_CLASS);
38
+ cm.state.activeLine = line;
39
+ });
40
+ }
41
+
42
+ function selectionChange(cm, sel) {
43
+ updateActiveLine(cm, sel.head.line);
38
44
  }
39
45
  })();
@@ -251,7 +251,7 @@
251
251
  var lex = inner.state.lexical;
252
252
  if (lex.info != "call") return;
253
253
 
254
- var ch, pos = lex.pos || 0, tabSize = cm.getOption("tabSize");
254
+ var ch, argPos = lex.pos || 0, tabSize = cm.getOption("tabSize");
255
255
  for (var line = cm.getCursor().line, e = Math.max(0, line - 9), found = false; line >= e; --line) {
256
256
  var str = cm.getLine(line), extra = 0;
257
257
  for (var pos = 0;;) {
@@ -268,7 +268,7 @@
268
268
  var start = Pos(line, ch);
269
269
  var cache = ts.cachedArgHints;
270
270
  if (cache && cache.doc == cm.getDoc() && cmpPos(start, cache.start) == 0)
271
- return showArgHints(ts, cm, pos);
271
+ return showArgHints(ts, cm, argPos);
272
272
 
273
273
  ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
274
274
  if (error || !data.type || !(/^fn\(/).test(data.type)) return;
@@ -279,7 +279,7 @@
279
279
  guess: data.guess,
280
280
  doc: cm.getDoc()
281
281
  };
282
- showArgHints(ts, cm, pos);
282
+ showArgHints(ts, cm, argPos);
283
283
  });
284
284
  }
285
285
 
@@ -36,31 +36,40 @@
36
36
  var killTrailing = options.killTrailingSpace !== false;
37
37
  var changes = [], curLine = "", curNo = from.line;
38
38
  var lines = cm.getRange(from, to, false);
39
+ if (!lines.length) return null;
40
+ var leadingSpace = lines[0].match(/^[ \t]*/)[0];
41
+
39
42
  for (var i = 0; i < lines.length; ++i) {
40
43
  var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
41
44
  if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) {
42
45
  curLine += " ";
43
46
  spaceInserted = 1;
44
47
  }
48
+ var spaceTrimmed = "";
49
+ if (i) {
50
+ spaceTrimmed = text.match(/^\s*/)[0];
51
+ text = text.slice(spaceTrimmed.length);
52
+ }
45
53
  curLine += text;
46
54
  if (i) {
47
- var firstBreak = curLine.length > column && findBreakPoint(curLine, column, wrapOn, killTrailing);
55
+ var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
56
+ findBreakPoint(curLine, column, wrapOn, killTrailing);
48
57
  // If this isn't broken, or is broken at a different point, remove old break
49
58
  if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
50
- changes.push({text: spaceInserted ? " " : "",
59
+ changes.push({text: [spaceInserted ? " " : ""],
51
60
  from: Pos(curNo, oldLen),
52
- to: Pos(curNo + 1, 0)});
61
+ to: Pos(curNo + 1, spaceTrimmed.length)});
53
62
  } else {
54
- curLine = text;
63
+ curLine = leadingSpace + text;
55
64
  ++curNo;
56
65
  }
57
66
  }
58
67
  while (curLine.length > column) {
59
68
  var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
60
- changes.push({text: "\n",
69
+ changes.push({text: ["", leadingSpace],
61
70
  from: Pos(curNo, bp.from),
62
71
  to: Pos(curNo, bp.to)});
63
- curLine = curLine.slice(bp.to);
72
+ curLine = leadingSpace + curLine.slice(bp.to);
64
73
  ++curNo;
65
74
  }
66
75
  }
@@ -70,17 +79,18 @@
70
79
  cm.replaceRange(change.text, change.from, change.to);
71
80
  }
72
81
  });
82
+ return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
73
83
  }
74
84
 
75
85
  CodeMirror.defineExtension("wrapParagraph", function(pos, options) {
76
86
  options = options || {};
77
87
  if (!pos) pos = this.getCursor();
78
88
  var para = findParagraph(this, pos, options);
79
- wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
89
+ return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
80
90
  });
81
91
 
82
92
  CodeMirror.defineExtension("wrapRange", function(from, to, options) {
83
- wrapRange(this, from, to, options || {});
93
+ return wrapRange(this, from, to, options || {});
84
94
  });
85
95
 
86
96
  CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) {
@@ -91,9 +101,11 @@
91
101
  paras.push(para);
92
102
  line = para.to;
93
103
  }
104
+ var madeChange = false;
94
105
  if (paras.length) cm.operation(function() {
95
106
  for (var i = paras.length - 1; i >= 0; --i)
96
- wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options);
107
+ madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options);
97
108
  });
109
+ return madeChange;
98
110
  });
99
111
  })();
@@ -201,6 +201,11 @@
201
201
  cm.on("change", function() { cm.setExtending(false); });
202
202
  }
203
203
 
204
+ function clearMark(cm) {
205
+ cm.setExtending(false);
206
+ cm.setCursor(cm.getCursor());
207
+ }
208
+
204
209
  function getInput(cm, msg, f) {
205
210
  if (cm.openDialog)
206
211
  cm.openDialog(msg + ": <input type=\"text\" style=\"width: 10em\"/>", f, {bottom: true});
@@ -234,6 +239,11 @@
234
239
  }
235
240
  }
236
241
 
242
+ function quit(cm) {
243
+ cm.execCommand("clearSearch");
244
+ clearMark(cm);
245
+ }
246
+
237
247
  // Actual keymap
238
248
 
239
249
  var keyMap = CodeMirror.keyMap.emacs = {
@@ -249,6 +259,7 @@
249
259
  }),
250
260
  "Alt-W": function(cm) {
251
261
  addToRing(cm.getSelection());
262
+ clearMark(cm);
252
263
  },
253
264
  "Ctrl-Y": function(cm) {
254
265
  var start = cm.getCursor();
@@ -334,7 +345,7 @@
334
345
  "Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"),
335
346
  "Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"),
336
347
  "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
337
- "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace",
348
+ "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace",
338
349
  "Alt-/": "autocomplete",
339
350
  "Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
340
351
 
@@ -84,6 +84,7 @@
84
84
  { keys: ['<End>'], type: 'keyToKey', toKeys: ['$'] },
85
85
  { keys: ['<PageUp>'], type: 'keyToKey', toKeys: ['<C-b>'] },
86
86
  { keys: ['<PageDown>'], type: 'keyToKey', toKeys: ['<C-f>'] },
87
+ { keys: ['<CR>'], type: 'keyToKey', toKeys: ['j', '^'], context: 'normal' },
87
88
  // Motions
88
89
  { keys: ['H'], type: 'motion',
89
90
  motion: 'moveToTopLine',
@@ -247,6 +248,12 @@
247
248
  actionArgs: { forward: true }},
248
249
  { keys: ['<C-o>'], type: 'action', action: 'jumpListWalk',
249
250
  actionArgs: { forward: false }},
251
+ { keys: ['<C-e>'], type: 'action',
252
+ action: 'scroll',
253
+ actionArgs: { forward: true, linewise: true }},
254
+ { keys: ['<C-y>'], type: 'action',
255
+ action: 'scroll',
256
+ actionArgs: { forward: false, linewise: true }},
250
257
  { keys: ['a'], type: 'action', action: 'enterInsertMode', isEdit: true,
251
258
  actionArgs: { insertAt: 'charAfter' }},
252
259
  { keys: ['A'], type: 'action', action: 'enterInsertMode', isEdit: true,
@@ -324,12 +331,16 @@
324
331
  CodeMirror.defineOption('vimMode', false, function(cm, val) {
325
332
  if (val) {
326
333
  cm.setOption('keyMap', 'vim');
334
+ cm.setOption('disableInput', true);
327
335
  CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
328
336
  cm.on('beforeSelectionChange', beforeSelectionChange);
329
337
  maybeInitVimState(cm);
338
+ CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm));
330
339
  } else if (cm.state.vim) {
331
340
  cm.setOption('keyMap', 'default');
341
+ cm.setOption('disableInput', false);
332
342
  cm.off('beforeSelectionChange', beforeSelectionChange);
343
+ CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm));
333
344
  cm.state.vim = null;
334
345
  }
335
346
  });
@@ -342,6 +353,18 @@
342
353
  head.ch--;
343
354
  }
344
355
  }
356
+ function getOnPasteFn(cm) {
357
+ var vim = cm.state.vim;
358
+ if (!vim.onPasteFn) {
359
+ vim.onPasteFn = function() {
360
+ if (!vim.insertMode) {
361
+ cm.setCursor(offsetCursor(cm.getCursor(), 0, 1));
362
+ actions.enterInsertMode(cm, {}, vim);
363
+ }
364
+ };
365
+ }
366
+ return vim.onPasteFn;
367
+ }
345
368
 
346
369
  var numberRegex = /[\d]/;
347
370
  var wordRegexp = [(/\w/), (/[^\w\s]/)], bigWordRegexp = [(/\S/)];
@@ -549,9 +572,9 @@
549
572
  maybeInitVimState_: maybeInitVimState,
550
573
 
551
574
  InsertModeKey: InsertModeKey,
552
- map: function(lhs, rhs) {
575
+ map: function(lhs, rhs, ctx) {
553
576
  // Add user defined key bindings.
554
- exCommandDispatcher.map(lhs, rhs);
577
+ exCommandDispatcher.map(lhs, rhs, ctx);
555
578
  },
556
579
  defineEx: function(name, prefix, func){
557
580
  if (name.indexOf(prefix) !== 0) {
@@ -833,11 +856,17 @@
833
856
  } else {
834
857
  // Find the best match in the list of matchedCommands.
835
858
  var context = vim.visualMode ? 'visual' : 'normal';
836
- var bestMatch = matchedCommands[0]; // Default to first in the list.
859
+ var bestMatch; // Default to first in the list.
837
860
  for (var i = 0; i < matchedCommands.length; i++) {
838
- if (matchedCommands[i].context == context) {
839
- bestMatch = matchedCommands[i];
861
+ var current = matchedCommands[i];
862
+ if (current.context == context) {
863
+ bestMatch = current;
840
864
  break;
865
+ } else if (!bestMatch && !current.context) {
866
+ // Only set an imperfect match to best match if no best match is
867
+ // set and the imperfect match is not restricted to another
868
+ // context.
869
+ bestMatch = current;
841
870
  }
842
871
  }
843
872
  return getFullyMatchedCommandOrNull(bestMatch);
@@ -1636,6 +1665,43 @@
1636
1665
  markPos = markPos ? markPos : cm.getCursor();
1637
1666
  cm.setCursor(markPos);
1638
1667
  },
1668
+ scroll: function(cm, actionArgs, vim) {
1669
+ if (vim.visualMode) {
1670
+ return;
1671
+ }
1672
+ var repeat = actionArgs.repeat || 1;
1673
+ var lineHeight = cm.defaultTextHeight();
1674
+ var top = cm.getScrollInfo().top;
1675
+ var delta = lineHeight * repeat;
1676
+ var newPos = actionArgs.forward ? top + delta : top - delta;
1677
+ var cursor = cm.getCursor();
1678
+ var cursorCoords = cm.charCoords(cursor, 'local');
1679
+ if (actionArgs.forward) {
1680
+ if (newPos > cursorCoords.top) {
1681
+ cursor.line += (newPos - cursorCoords.top) / lineHeight;
1682
+ cursor.line = Math.ceil(cursor.line);
1683
+ cm.setCursor(cursor);
1684
+ cursorCoords = cm.charCoords(cursor, 'local');
1685
+ cm.scrollTo(null, cursorCoords.top);
1686
+ } else {
1687
+ // Cursor stays within bounds. Just reposition the scroll window.
1688
+ cm.scrollTo(null, newPos);
1689
+ }
1690
+ } else {
1691
+ var newBottom = newPos + cm.getScrollInfo().clientHeight;
1692
+ if (newBottom < cursorCoords.bottom) {
1693
+ cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight;
1694
+ cursor.line = Math.floor(cursor.line);
1695
+ cm.setCursor(cursor);
1696
+ cursorCoords = cm.charCoords(cursor, 'local');
1697
+ cm.scrollTo(
1698
+ null, cursorCoords.bottom - cm.getScrollInfo().clientHeight);
1699
+ } else {
1700
+ // Cursor stays within bounds. Just reposition the scroll window.
1701
+ cm.scrollTo(null, newPos);
1702
+ }
1703
+ }
1704
+ },
1639
1705
  scrollToCursor: function(cm, actionArgs) {
1640
1706
  var lineNum = cm.getCursor().line;
1641
1707
  var charCoords = cm.charCoords({line: lineNum, ch: 0}, 'local');
@@ -1691,6 +1757,7 @@
1691
1757
  cm.setCursor(motions.moveToFirstNonWhiteSpaceCharacter(cm));
1692
1758
  }
1693
1759
  cm.setOption('keyMap', 'vim-insert');
1760
+ cm.setOption('disableInput', false);
1694
1761
  if (actionArgs && actionArgs.replace) {
1695
1762
  // Handle Replace-mode as a special case of insert mode.
1696
1763
  cm.toggleOverwrite(true);
@@ -2896,14 +2963,16 @@
2896
2963
  // pair of commands that have a shared prefix, at least one of their
2897
2964
  // shortNames must not match the prefix of the other command.
2898
2965
  var defaultExCommandMap = [
2899
- { name: 'map', type: 'builtIn' },
2900
- { name: 'write', shortName: 'w', type: 'builtIn' },
2901
- { name: 'undo', shortName: 'u', type: 'builtIn' },
2902
- { name: 'redo', shortName: 'red', type: 'builtIn' },
2903
- { name: 'sort', shortName: 'sor', type: 'builtIn'},
2904
- { name: 'substitute', shortName: 's', type: 'builtIn'},
2905
- { name: 'nohlsearch', shortName: 'noh', type: 'builtIn'},
2906
- { name: 'delmarks', shortName: 'delm', type: 'builtin'}
2966
+ { name: 'map' },
2967
+ { name: 'nmap', shortName: 'nm' },
2968
+ { name: 'vmap', shortName: 'vm' },
2969
+ { name: 'write', shortName: 'w' },
2970
+ { name: 'undo', shortName: 'u' },
2971
+ { name: 'redo', shortName: 'red' },
2972
+ { name: 'sort', shortName: 'sor' },
2973
+ { name: 'substitute', shortName: 's' },
2974
+ { name: 'nohlsearch', shortName: 'noh' },
2975
+ { name: 'delmarks', shortName: 'delm' }
2907
2976
  ];
2908
2977
  Vim.ExCommandDispatcher = function() {
2909
2978
  this.buildCommandMap_();
@@ -2955,6 +3024,7 @@
2955
3024
  exCommands[commandName](cm, params);
2956
3025
  } catch(e) {
2957
3026
  showConfirm(cm, e);
3027
+ throw e;
2958
3028
  }
2959
3029
  },
2960
3030
  parseInput_: function(cm, inputStream, result) {
@@ -3037,8 +3107,9 @@
3037
3107
  this.commandMap_[key] = command;
3038
3108
  }
3039
3109
  },
3040
- map: function(lhs, rhs) {
3110
+ map: function(lhs, rhs, ctx) {
3041
3111
  if (lhs != ':' && lhs.charAt(0) == ':') {
3112
+ if (ctx) { throw Error('Mode not supported for ex mappings'); }
3042
3113
  var commandName = lhs.substring(1);
3043
3114
  if (rhs != ':' && rhs.charAt(0) == ':') {
3044
3115
  // Ex to Ex mapping
@@ -3058,17 +3129,21 @@
3058
3129
  } else {
3059
3130
  if (rhs != ':' && rhs.charAt(0) == ':') {
3060
3131
  // Key to Ex mapping.
3061
- defaultKeymap.unshift({
3132
+ var mapping = {
3062
3133
  keys: parseKeyString(lhs),
3063
3134
  type: 'keyToEx',
3064
- exArgs: { input: rhs.substring(1) }});
3135
+ exArgs: { input: rhs.substring(1) }};
3136
+ if (ctx) { mapping.context = ctx; }
3137
+ defaultKeymap.unshift(mapping);
3065
3138
  } else {
3066
3139
  // Key to key mapping
3067
- defaultKeymap.unshift({
3140
+ var mapping = {
3068
3141
  keys: parseKeyString(lhs),
3069
3142
  type: 'keyToKey',
3070
3143
  toKeys: parseKeyString(rhs)
3071
- });
3144
+ };
3145
+ if (ctx) { mapping.context = ctx; }
3146
+ defaultKeymap.unshift(mapping);
3072
3147
  }
3073
3148
  }
3074
3149
  }
@@ -3090,7 +3165,7 @@
3090
3165
  }
3091
3166
 
3092
3167
  var exCommands = {
3093
- map: function(cm, params) {
3168
+ map: function(cm, params, ctx) {
3094
3169
  var mapArgs = params.args;
3095
3170
  if (!mapArgs || mapArgs.length < 2) {
3096
3171
  if (cm) {
@@ -3098,8 +3173,10 @@
3098
3173
  }
3099
3174
  return;
3100
3175
  }
3101
- exCommandDispatcher.map(mapArgs[0], mapArgs[1], cm);
3176
+ exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx);
3102
3177
  },
3178
+ nmap: function(cm, params) { this.map(cm, params, 'normal'); },
3179
+ vmap: function(cm, params) { this.map(cm, params, 'visual'); },
3103
3180
  move: function(cm, params) {
3104
3181
  commandDispatcher.processCommand(cm, cm.state.vim, {
3105
3182
  type: 'motion',
@@ -3115,7 +3192,7 @@
3115
3192
  var args = new CodeMirror.StringStream(params.argString);
3116
3193
  if (args.eat('!')) { reverse = true; }
3117
3194
  if (args.eol()) { return; }
3118
- if (!args.eatSpace()) { throw new Error('invalid arguments ' + args.match(/.*/)[0]); }
3195
+ if (!args.eatSpace()) { return 'Invalid arguments'; }
3119
3196
  var opts = args.match(/[a-z]+/);
3120
3197
  if (opts) {
3121
3198
  opts = opts[0];
@@ -3124,13 +3201,17 @@
3124
3201
  var decimal = opts.indexOf('d') != -1 && 1;
3125
3202
  var hex = opts.indexOf('x') != -1 && 1;
3126
3203
  var octal = opts.indexOf('o') != -1 && 1;
3127
- if (decimal + hex + octal > 1) { throw new Error('invalid arguments'); }
3204
+ if (decimal + hex + octal > 1) { return 'Invalid arguments'; }
3128
3205
  number = decimal && 'decimal' || hex && 'hex' || octal && 'octal';
3129
3206
  }
3130
- if (args.eatSpace() && args.match(/\/.*\//)) { throw new Error('patterns not supported'); }
3207
+ if (args.eatSpace() && args.match(/\/.*\//)) { 'patterns not supported'; }
3131
3208
  }
3132
3209
  }
3133
- parseArgs();
3210
+ var err = parseArgs();
3211
+ if (err) {
3212
+ showConfirm(cm, err + ': ' + params.argString);
3213
+ return;
3214
+ }
3134
3215
  var lineStart = params.line || cm.firstLine();
3135
3216
  var lineEnd = params.lineEnd || params.line || cm.lastLine();
3136
3217
  if (lineStart == lineEnd) { return; }
@@ -3251,13 +3332,13 @@
3251
3332
  clearSearchHighlight(cm);
3252
3333
  },
3253
3334
  delmarks: function(cm, params) {
3254
- if (!params.argString || !params.argString.trim()) {
3335
+ if (!params.argString || !trim(params.argString)) {
3255
3336
  showConfirm(cm, 'Argument required');
3256
3337
  return;
3257
3338
  }
3258
3339
 
3259
3340
  var state = cm.state.vim;
3260
- var stream = new CodeMirror.StringStream(params.argString.trim());
3341
+ var stream = new CodeMirror.StringStream(trim(params.argString));
3261
3342
  while (!stream.eol()) {
3262
3343
  stream.eatSpace();
3263
3344
 
@@ -3394,7 +3475,8 @@
3394
3475
  // Actually do replace.
3395
3476
  next();
3396
3477
  if (done) {
3397
- throw new Error('No matches for ' + query.source);
3478
+ showConfirm(cm, 'No matches for ' + query.source);
3479
+ return;
3398
3480
  }
3399
3481
  if (!confirm) {
3400
3482
  replaceAll();
@@ -3445,7 +3527,6 @@
3445
3527
 
3446
3528
  var cmToVimKeymap = {
3447
3529
  'nofallthrough': true,
3448
- 'disableInput': true,
3449
3530
  'style': 'fat-cursor'
3450
3531
  };
3451
3532
  function bindKeys(keys, modifier) {
@@ -3492,6 +3573,7 @@
3492
3573
  cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
3493
3574
  vim.insertMode = false;
3494
3575
  cm.setOption('keyMap', 'vim');
3576
+ cm.setOption('disableInput', true);
3495
3577
  cm.toggleOverwrite(false); // exit replace mode if we were in it.
3496
3578
  CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
3497
3579
  }