codemirror-rails 5.2 → 5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/codemirror/rails/version.rb +2 -2
  3. data/vendor/assets/javascripts/codemirror.js +34 -27
  4. data/vendor/assets/javascripts/codemirror/addons/display/rulers.js +1 -2
  5. data/vendor/assets/javascripts/codemirror/addons/edit/closebrackets.js +1 -0
  6. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +14 -23
  7. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +12 -3
  8. data/vendor/assets/javascripts/codemirror/addons/lint/lint.js +6 -6
  9. data/vendor/assets/javascripts/codemirror/addons/search/search.js +1 -1
  10. data/vendor/assets/javascripts/codemirror/addons/search/searchcursor.js +2 -2
  11. data/vendor/assets/javascripts/codemirror/addons/tern/worker.js +1 -1
  12. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +64 -67
  13. data/vendor/assets/javascripts/codemirror/modes/apl.js +1 -2
  14. data/vendor/assets/javascripts/codemirror/modes/asn.1.js +204 -0
  15. data/vendor/assets/javascripts/codemirror/modes/asterisk.js +2 -4
  16. data/vendor/assets/javascripts/codemirror/modes/clike.js +98 -36
  17. data/vendor/assets/javascripts/codemirror/modes/css.js +1 -16
  18. data/vendor/assets/javascripts/codemirror/modes/cypher.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/modes/dylan.js +18 -26
  20. data/vendor/assets/javascripts/codemirror/modes/ecl.js +1 -2
  21. data/vendor/assets/javascripts/codemirror/modes/eiffel.js +0 -2
  22. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +2 -2
  23. data/vendor/assets/javascripts/codemirror/modes/julia.js +0 -2
  24. data/vendor/assets/javascripts/codemirror/modes/livescript.js +2 -2
  25. data/vendor/assets/javascripts/codemirror/modes/mathematica.js +175 -0
  26. data/vendor/assets/javascripts/codemirror/modes/php.js +1 -0
  27. data/vendor/assets/javascripts/codemirror/modes/pig.js +15 -25
  28. data/vendor/assets/javascripts/codemirror/modes/sql.js +2 -2
  29. data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +36 -47
  30. data/vendor/assets/javascripts/codemirror/modes/tiki.js +8 -19
  31. data/vendor/assets/javascripts/codemirror/modes/ttcn-cfg.js +214 -0
  32. data/vendor/assets/javascripts/codemirror/modes/ttcn.js +283 -0
  33. data/vendor/assets/javascripts/codemirror/modes/xquery.js +30 -40
  34. data/vendor/assets/stylesheets/codemirror/addons/dialog/dialog.css +2 -2
  35. data/vendor/assets/stylesheets/codemirror/themes/monokai.css +1 -0
  36. data/vendor/assets/stylesheets/codemirror/themes/ttcn.css +66 -0
  37. metadata +8 -7
  38. data/vendor/assets/javascripts/codemirror/addons/mode/multiplex_test.js +0 -33
  39. data/vendor/assets/javascripts/codemirror/modes/less_test.js +0 -54
  40. data/vendor/assets/javascripts/codemirror/modes/scss_test.js +0 -110
  41. data/vendor/assets/javascripts/codemirror/modes/test.js +0 -67
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 050b051a53f2101672d02e5b5a5b0e8882e01efa
4
- data.tar.gz: 0a4451cf450a3dd4bd78c7269d779dfdda8fd7dd
3
+ metadata.gz: c6ddde433ae7b37ee0173fe1a42d41cd91f3744d
4
+ data.tar.gz: b69c9951146b7b058e70a132e59ea6572d16c853
5
5
  SHA512:
6
- metadata.gz: 00407212b29c41420da933d548ab4d703276f80a539a5593ac6ca21127f5837a7fd0fbf21af9414dd1bf275bbf96fa0de3c83be7834d7118767f6f29de00da45
7
- data.tar.gz: 49f03cf54ac054fd36d13e8e038956647eeb0120db8c3186a5036575d185e8ca71d2c1e9556bdcf675c95e2dffefb016772dfb5c59664cdad12caed2af2df4bb
6
+ metadata.gz: cbd3e9ba7e1b89305aaa9f361cf5f7859b9a46c0297974d5211ffd357eb5dc0d5b0453eb0715bb46e3f786dd02d871ea5b9712eda1886b27e20585c79c86ac9d
7
+ data.tar.gz: b232672158c10203601d827f7a3251b5c717f66ba0ce6e08b1e07537bf20854e42fd4a07c025bc5ddf84137544c4d2371fa4a89afbfc04d5720a3bd883cc017f
@@ -1,6 +1,6 @@
1
1
  module Codemirror
2
2
  module Rails
3
- VERSION = '5.2'
4
- CODEMIRROR_VERSION = '5.2'
3
+ VERSION = '5.3'
4
+ CODEMIRROR_VERSION = '5.3'
5
5
  end
6
6
  end
@@ -728,12 +728,9 @@
728
728
  }
729
729
 
730
730
  function postUpdateDisplay(cm, update) {
731
- var force = update.force, viewport = update.viewport;
731
+ var viewport = update.viewport;
732
732
  for (var first = true;; first = false) {
733
- if (first && cm.options.lineWrapping && update.oldDisplayWidth != displayWidth(cm)) {
734
- force = true;
735
- } else {
736
- force = false;
733
+ if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
737
734
  // Clip forced viewport to actual scrollable area.
738
735
  if (viewport && viewport.top != null)
739
736
  viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
@@ -1108,32 +1105,40 @@
1108
1105
  origin: origin || (cm.state.pasteIncoming ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
1109
1106
  makeChange(cm.doc, changeEvent);
1110
1107
  signalLater(cm, "inputRead", cm, changeEvent);
1111
- // When an 'electric' character is inserted, immediately trigger a reindent
1112
- if (inserted && !cm.state.pasteIncoming && cm.options.electricChars &&
1113
- cm.options.smartIndent && range.head.ch < 100 &&
1114
- (!i || sel.ranges[i - 1].head.line != range.head.line)) {
1115
- var mode = cm.getModeAt(range.head);
1116
- var end = changeEnd(changeEvent);
1117
- var indented = false;
1118
- if (mode.electricChars) {
1119
- for (var j = 0; j < mode.electricChars.length; j++)
1120
- if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
1121
- indented = indentLine(cm, end.line, "smart");
1122
- break;
1123
- }
1124
- } else if (mode.electricInput) {
1125
- if (mode.electricInput.test(getLine(doc, end.line).text.slice(0, end.ch)))
1126
- indented = indentLine(cm, end.line, "smart");
1127
- }
1128
- if (indented) signalLater(cm, "electricInput", cm, end.line);
1129
- }
1130
1108
  }
1109
+ if (inserted && !cm.state.pasteIncoming)
1110
+ triggerElectric(cm, inserted);
1111
+
1131
1112
  ensureCursorVisible(cm);
1132
1113
  cm.curOp.updateInput = updateInput;
1133
1114
  cm.curOp.typing = true;
1134
1115
  cm.state.pasteIncoming = cm.state.cutIncoming = false;
1135
1116
  }
1136
1117
 
1118
+ function triggerElectric(cm, inserted) {
1119
+ // When an 'electric' character is inserted, immediately trigger a reindent
1120
+ if (!cm.options.electricChars || !cm.options.smartIndent) return;
1121
+ var sel = cm.doc.sel;
1122
+
1123
+ for (var i = sel.ranges.length - 1; i >= 0; i--) {
1124
+ var range = sel.ranges[i];
1125
+ if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue;
1126
+ var mode = cm.getModeAt(range.head);
1127
+ var indented = false;
1128
+ if (mode.electricChars) {
1129
+ for (var j = 0; j < mode.electricChars.length; j++)
1130
+ if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
1131
+ indented = indentLine(cm, range.head.line, "smart");
1132
+ break;
1133
+ }
1134
+ } else if (mode.electricInput) {
1135
+ if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
1136
+ indented = indentLine(cm, range.head.line, "smart");
1137
+ }
1138
+ if (indented) signalLater(cm, "electricInput", cm, range.head.line);
1139
+ }
1140
+ }
1141
+
1137
1142
  function copyableRanges(cm) {
1138
1143
  var text = [], ranges = [];
1139
1144
  for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
@@ -1836,7 +1841,7 @@
1836
1841
  var partPos = getBidiPartAt(order, pos.ch);
1837
1842
  side = partPos % 2 ? "right" : "left";
1838
1843
  }
1839
- var result = nodeAndOffsetInLineMap(info.map, pos.ch, "left");
1844
+ var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
1840
1845
  result.offset = result.collapse == "right" ? result.end : result.start;
1841
1846
  return result;
1842
1847
  }
@@ -5053,6 +5058,8 @@
5053
5058
  return commands[cmd](this);
5054
5059
  },
5055
5060
 
5061
+ triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
5062
+
5056
5063
  findPosH: function(from, amount, unit, visually) {
5057
5064
  var dir = 1;
5058
5065
  if (amount < 0) { dir = -1; amount = -amount; }
@@ -5720,7 +5727,7 @@
5720
5727
  for (var i = 0; i < keys.length; i++) {
5721
5728
  var val, name;
5722
5729
  if (i == keys.length - 1) {
5723
- name = keyname;
5730
+ name = keys.join(" ");
5724
5731
  val = value;
5725
5732
  } else {
5726
5733
  name = keys.slice(0, i + 1).join(" ");
@@ -8732,7 +8739,7 @@
8732
8739
 
8733
8740
  // THE END
8734
8741
 
8735
- CodeMirror.version = "5.2.0";
8742
+ CodeMirror.version = "5.3.0";
8736
8743
 
8737
8744
  return CodeMirror;
8738
8745
  });
@@ -38,7 +38,7 @@
38
38
  for (var i = 0; i < val.length; i++) {
39
39
  var elt = document.createElement("div");
40
40
  elt.className = "CodeMirror-ruler";
41
- var col, cls = null, conf = val[i];
41
+ var col, conf = val[i];
42
42
  if (typeof conf == "number") {
43
43
  col = conf;
44
44
  } else {
@@ -47,7 +47,6 @@
47
47
  if (conf.color) elt.style.borderColor = conf.color;
48
48
  if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
49
49
  if (conf.width) elt.style.borderLeftWidth = conf.width;
50
- cls = val[i].className;
51
50
  }
52
51
  elt.style.left = (left + col * cw) + "px";
53
52
  elt.style.top = "-50px";
@@ -147,6 +147,7 @@
147
147
  cm.replaceSelections(sels, "around");
148
148
  } else if (type == "both") {
149
149
  cm.replaceSelection(left + right, null);
150
+ cm.triggerElectric(left + right);
150
151
  cm.execCommand("goCharLeft");
151
152
  } else if (type == "addFour") {
152
153
  cm.replaceSelection(left + left + left + left, "before");
@@ -33,7 +33,7 @@
33
33
  if (!completion.options.hint) return;
34
34
 
35
35
  CodeMirror.signal(this, "startCompletion", this);
36
- completion.update();
36
+ completion.update(true);
37
37
  });
38
38
 
39
39
  function Completion(cm, options) {
@@ -61,6 +61,7 @@
61
61
  this.tick = null;
62
62
  this.cm.off("cursorActivity", this.activityFunc);
63
63
 
64
+ if (this.widget && this.data) CodeMirror.signal(this.data, "close");
64
65
  if (this.widget) this.widget.close();
65
66
  CodeMirror.signal(this.cm, "endCompletion", this.cm);
66
67
  },
@@ -78,15 +79,6 @@
78
79
  this.close();
79
80
  },
80
81
 
81
- showHints: function(data) {
82
- if (!data || !data.list.length || !this.active()) return this.close();
83
-
84
- if (this.options.completeSingle && data.list.length == 1)
85
- this.pick(data, 0);
86
- else
87
- this.showWidget(data);
88
- },
89
-
90
82
  cursorActivity: function() {
91
83
  if (this.debounce) {
92
84
  cancelAnimationFrame(this.debounce);
@@ -105,35 +97,34 @@
105
97
  }
106
98
  },
107
99
 
108
- update: function() {
100
+ update: function(first) {
109
101
  if (this.tick == null) return;
110
102
  if (this.data) CodeMirror.signal(this.data, "update");
111
103
  if (!this.options.hint.async) {
112
- this.finishUpdate(this.options.hint(this.cm, this.options), myTick);
104
+ this.finishUpdate(this.options.hint(this.cm, this.options), first);
113
105
  } else {
114
106
  var myTick = ++this.tick, self = this;
115
107
  this.options.hint(this.cm, function(data) {
116
- if (self.tick == myTick) self.finishUpdate(data);
108
+ if (self.tick == myTick) self.finishUpdate(data, first);
117
109
  }, this.options);
118
110
  }
119
111
  },
120
112
 
121
- finishUpdate: function(data) {
113
+ finishUpdate: function(data, first) {
122
114
  this.data = data;
123
- var picked = this.widget && this.widget.picked;
115
+
116
+ var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
124
117
  if (this.widget) this.widget.close();
125
118
  if (data && data.list.length) {
126
- if (picked && data.list.length == 1) this.pick(data, 0);
127
- else this.widget = new Widget(this, data);
119
+ if (picked && data.list.length == 1) {
120
+ this.pick(data, 0);
121
+ } else {
122
+ this.widget = new Widget(this, data);
123
+ CodeMirror.signal(data, "shown");
124
+ }
128
125
  }
129
126
  },
130
127
 
131
- showWidget: function(data) {
132
- this.data = data;
133
- this.widget = new Widget(this, data);
134
- CodeMirror.signal(data, "shown");
135
- },
136
-
137
128
  buildOptions: function(options) {
138
129
  var editor = this.cm.options.hintOptions;
139
130
  var out = {};
@@ -112,9 +112,14 @@
112
112
  string = nameParts.pop();
113
113
  var table = nameParts.join(".");
114
114
 
115
+ var alias = false;
116
+ var aliasTable = table;
115
117
  // Check if table is available. If not, find table by Alias
116
- if (!getItem(tables, table))
118
+ if (!getItem(tables, table)) {
119
+ var oldTable = table;
117
120
  table = findTableByAlias(table, editor);
121
+ if (table !== oldTable) alias = true;
122
+ }
118
123
 
119
124
  var columns = getItem(tables, table);
120
125
  if (columns && columns.columns)
@@ -123,7 +128,9 @@
123
128
  if (columns) {
124
129
  addMatches(result, string, columns, function(w) {
125
130
  if (typeof w == "string") {
126
- w = table + "." + w;
131
+ var tableInsert = table;
132
+ if (alias == true) tableInsert = aliasTable;
133
+ w = tableInsert + "." + w;
127
134
  } else {
128
135
  w = shallowClone(w);
129
136
  w.text = table + "." + w.text;
@@ -205,6 +212,7 @@
205
212
  CodeMirror.registerHelper("hint", "sql", function(editor, options) {
206
213
  tables = (options && options.tables) || {};
207
214
  var defaultTableName = options && options.defaultTable;
215
+ var disableKeywords = options && options.disableKeywords;
208
216
  defaultTable = defaultTableName && getItem(tables, defaultTableName);
209
217
  keywords = keywords || getKeywords(editor);
210
218
 
@@ -237,7 +245,8 @@
237
245
  } else {
238
246
  addMatches(result, search, tables, function(w) {return w;});
239
247
  addMatches(result, search, defaultTable, function(w) {return w;});
240
- addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
248
+ if (!disableKeywords)
249
+ addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
241
250
  }
242
251
 
243
252
  return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
@@ -63,11 +63,9 @@
63
63
  this.onMouseOver = function(e) { onMouseOver(cm, e); };
64
64
  }
65
65
 
66
- function parseOptions(cm, options) {
66
+ function parseOptions(_cm, options) {
67
67
  if (options instanceof Function) return {getAnnotations: options};
68
68
  if (!options || options === true) options = {};
69
- if (!options.getAnnotations) options.getAnnotations = cm.getHelper(CodeMirror.Pos(0, 0), "lint");
70
- if (!options.getAnnotations) throw new Error("Required option 'getAnnotations' missing (lint addon)");
71
69
  return options;
72
70
  }
73
71
 
@@ -120,10 +118,12 @@
120
118
  function startLinting(cm) {
121
119
  var state = cm.state.lint, options = state.options;
122
120
  var passOptions = options.options || options; // Support deprecated passing of `options` property in options
123
- if (options.async || options.getAnnotations.async)
124
- options.getAnnotations(cm.getValue(), updateLinting, passOptions, cm);
121
+ var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint");
122
+ if (!getAnnotations) return;
123
+ if (options.async || getAnnotations.async)
124
+ getAnnotations(cm.getValue(), updateLinting, passOptions, cm);
125
125
  else
126
- updateLinting(cm, options.getAnnotations(cm.getValue(), passOptions, cm));
126
+ updateLinting(cm, getAnnotations(cm.getValue(), passOptions, cm));
127
127
  }
128
128
 
129
129
  function updateLinting(cm, annotationsNotSorted) {
@@ -118,7 +118,7 @@
118
118
  var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
119
119
  function replace(cm, all) {
120
120
  if (cm.getOption("readOnly")) return;
121
- var query = cm.getSelection() || getSearchState().lastQuery;
121
+ var query = cm.getSelection() || getSearchState(cm).lastQuery;
122
122
  dialog(cm, replaceQueryDialog, "Replace:", query, function(query) {
123
123
  if (!query) return;
124
124
  query = parseQuery(query);
@@ -177,9 +177,9 @@
177
177
  });
178
178
 
179
179
  CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
180
- var ranges = [], next;
180
+ var ranges = [];
181
181
  var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
182
- while (next = cur.findNext()) {
182
+ while (cur.findNext()) {
183
183
  if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
184
184
  ranges.push({anchor: cur.from(), head: cur.to()});
185
185
  }
@@ -39,6 +39,6 @@ function startServer(defs, plugins, scripts) {
39
39
  });
40
40
  }
41
41
 
42
- var console = {
42
+ this.console = {
43
43
  log: function(v) { postMessage({type: "debug", message: v}); }
44
44
  };
@@ -3,42 +3,16 @@
3
3
 
4
4
  /**
5
5
  * Supported keybindings:
6
+ * Too many to list. Refer to defaultKeyMap below.
6
7
  *
7
- * Motion:
8
- * h, j, k, l
9
- * gj, gk
10
- * e, E, w, W, b, B, ge, gE
11
- * f<character>, F<character>, t<character>, T<character>
12
- * $, ^, 0, -, +, _
13
- * gg, G
14
- * %
15
- * '<character>, `<character>
16
- *
17
- * Operator:
18
- * d, y, c
19
- * dd, yy, cc
20
- * g~, g~g~
21
- * >, <, >>, <<
22
- *
23
- * Operator-Motion:
24
- * x, X, D, Y, C, ~
25
- *
26
- * Action:
27
- * a, i, s, A, I, S, o, O
28
- * zz, z., z<CR>, zt, zb, z-
29
- * J
30
- * u, Ctrl-r
31
- * m<character>
32
- * r<character>
33
- *
34
- * Modes:
35
- * ESC - leave insert mode, visual mode, and clear input state.
36
- * Ctrl-[, Ctrl-c - same as ESC.
8
+ * Supported Ex commands:
9
+ * Refer to defaultExCommandMap below.
37
10
  *
38
11
  * Registers: unnamed, -, a-z, A-Z, 0-9
39
12
  * (Does not respect the special case for number registers when delete
40
13
  * operator is made with these commands: %, (, ), , /, ?, n, N, {, } )
41
14
  * TODO: Implement the remaining registers.
15
+ *
42
16
  * Marks: a-z, A-Z, and 0-9
43
17
  * TODO: Implement the remaining special marks. They have more complex
44
18
  * behavior.
@@ -57,6 +31,7 @@
57
31
  * 6. Motion, operator, and action implementations
58
32
  * 7. Helper functions for the key handler, motions, operators, and actions
59
33
  * 8. Set up Vim to work as a keymap for CodeMirror.
34
+ * 9. Ex command implementations.
60
35
  */
61
36
 
62
37
  (function(mod) {
@@ -227,6 +202,34 @@
227
202
  { keys: ':', type: 'ex' }
228
203
  ];
229
204
 
205
+ /**
206
+ * Ex commands
207
+ * Care must be taken when adding to the default Ex command map. For any
208
+ * pair of commands that have a shared prefix, at least one of their
209
+ * shortNames must not match the prefix of the other command.
210
+ */
211
+ var defaultExCommandMap = [
212
+ { name: 'colorscheme', shortName: 'colo' },
213
+ { name: 'map' },
214
+ { name: 'imap', shortName: 'im' },
215
+ { name: 'nmap', shortName: 'nm' },
216
+ { name: 'vmap', shortName: 'vm' },
217
+ { name: 'unmap' },
218
+ { name: 'write', shortName: 'w' },
219
+ { name: 'undo', shortName: 'u' },
220
+ { name: 'redo', shortName: 'red' },
221
+ { name: 'set', shortName: 'se' },
222
+ { name: 'set', shortName: 'se' },
223
+ { name: 'setlocal', shortName: 'setl' },
224
+ { name: 'setglobal', shortName: 'setg' },
225
+ { name: 'sort', shortName: 'sor' },
226
+ { name: 'substitute', shortName: 's', possiblyAsync: true },
227
+ { name: 'nohlsearch', shortName: 'noh' },
228
+ { name: 'delmarks', shortName: 'delm' },
229
+ { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },
230
+ { name: 'global', shortName: 'g' }
231
+ ];
232
+
230
233
  var Pos = CodeMirror.Pos;
231
234
 
232
235
  var Vim = function() {
@@ -463,7 +466,7 @@
463
466
  }
464
467
  // The 'filetype' option proxies to the CodeMirror 'mode' option.
465
468
  if (name === undefined) {
466
- var mode = cm.getMode().name;
469
+ var mode = cm.getOption('mode');
467
470
  return mode == 'null' ? '' : mode;
468
471
  } else {
469
472
  var mode = name == '' ? 'null' : name;
@@ -689,7 +692,9 @@
689
692
  getOption: getOption,
690
693
  defineOption: defineOption,
691
694
  defineEx: function(name, prefix, func){
692
- if (name.indexOf(prefix) !== 0) {
695
+ if (!prefix) {
696
+ prefix = name;
697
+ } else if (name.indexOf(prefix) !== 0) {
693
698
  throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered');
694
699
  }
695
700
  exCommands[name]=func;
@@ -3635,13 +3640,17 @@
3635
3640
  // Translates the replace part of a search and replace from ex (vim) syntax into
3636
3641
  // javascript form. Similar to translateRegex, but additionally fixes back references
3637
3642
  // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'.
3643
+ var charUnescapes = {'\\n': '\n', '\\r': '\r', '\\t': '\t'};
3638
3644
  function translateRegexReplace(str) {
3639
3645
  var escapeNextChar = false;
3640
3646
  var out = [];
3641
3647
  for (var i = -1; i < str.length; i++) {
3642
3648
  var c = str.charAt(i) || '';
3643
3649
  var n = str.charAt(i+1) || '';
3644
- if (escapeNextChar) {
3650
+ if (charUnescapes[c + n]) {
3651
+ out.push(charUnescapes[c+n]);
3652
+ i++;
3653
+ } else if (escapeNextChar) {
3645
3654
  // At any point in the loop, escapeNextChar is true if the previous
3646
3655
  // character was a '\' and was not escaped.
3647
3656
  out.push(c);
@@ -3669,6 +3678,7 @@
3669
3678
  }
3670
3679
 
3671
3680
  // Unescape \ and / in the replace part, for PCRE mode.
3681
+ var unescapes = {'\\/': '/', '\\\\': '\\', '\\n': '\n', '\\r': '\r', '\\t': '\t'};
3672
3682
  function unescapeRegexReplace(str) {
3673
3683
  var stream = new CodeMirror.StringStream(str);
3674
3684
  var output = [];
@@ -3677,13 +3687,15 @@
3677
3687
  while (stream.peek() && stream.peek() != '\\') {
3678
3688
  output.push(stream.next());
3679
3689
  }
3680
- if (stream.match('\\/', true)) {
3681
- // \/ => /
3682
- output.push('/');
3683
- } else if (stream.match('\\\\', true)) {
3684
- // \\ => \
3685
- output.push('\\');
3686
- } else {
3690
+ var matched = false;
3691
+ for (var matcher in unescapes) {
3692
+ if (stream.match(matcher, true)) {
3693
+ matched = true;
3694
+ output.push(unescapes[matcher]);
3695
+ break;
3696
+ }
3697
+ }
3698
+ if (!matched) {
3687
3699
  // Don't change anything
3688
3700
  output.push(stream.next());
3689
3701
  }
@@ -3913,31 +3925,6 @@
3913
3925
  return {top: from.line, bottom: to.line};
3914
3926
  }
3915
3927
 
3916
- // Ex command handling
3917
- // Care must be taken when adding to the default Ex command map. For any
3918
- // pair of commands that have a shared prefix, at least one of their
3919
- // shortNames must not match the prefix of the other command.
3920
- var defaultExCommandMap = [
3921
- { name: 'colorscheme', shortName: 'colo' },
3922
- { name: 'map' },
3923
- { name: 'imap', shortName: 'im' },
3924
- { name: 'nmap', shortName: 'nm' },
3925
- { name: 'vmap', shortName: 'vm' },
3926
- { name: 'unmap' },
3927
- { name: 'write', shortName: 'w' },
3928
- { name: 'undo', shortName: 'u' },
3929
- { name: 'redo', shortName: 'red' },
3930
- { name: 'set', shortName: 'se' },
3931
- { name: 'set', shortName: 'se' },
3932
- { name: 'setlocal', shortName: 'setl' },
3933
- { name: 'setglobal', shortName: 'setg' },
3934
- { name: 'sort', shortName: 'sor' },
3935
- { name: 'substitute', shortName: 's', possiblyAsync: true },
3936
- { name: 'nohlsearch', shortName: 'noh' },
3937
- { name: 'delmarks', shortName: 'delm' },
3938
- { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true },
3939
- { name: 'global', shortName: 'g' }
3940
- ];
3941
3928
  var ExCommandDispatcher = function() {
3942
3929
  this.buildCommandMap_();
3943
3930
  };
@@ -4483,6 +4470,9 @@
4483
4470
  var query = state.getQuery();
4484
4471
  var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line;
4485
4472
  var lineEnd = params.lineEnd || lineStart;
4473
+ if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) {
4474
+ lineEnd = Infinity;
4475
+ }
4486
4476
  if (count) {
4487
4477
  lineStart = lineEnd;
4488
4478
  lineEnd = lineStart + count - 1;
@@ -4601,10 +4591,9 @@
4601
4591
  searchCursor.replace(newText);
4602
4592
  }
4603
4593
  function next() {
4604
- var found;
4605
4594
  // The below only loops to skip over multiple occurrences on the same
4606
4595
  // line when 'global' is not true.
4607
- while(found = searchCursor.findNext() &&
4596
+ while(searchCursor.findNext() &&
4608
4597
  isInRange(searchCursor.from(), lineStart, lineEnd)) {
4609
4598
  if (!global && lastPos && searchCursor.from().line == lastPos.line) {
4610
4599
  continue;
@@ -4779,6 +4768,14 @@
4779
4768
 
4780
4769
  function executeMacroRegister(cm, vim, macroModeState, registerName) {
4781
4770
  var register = vimGlobalState.registerController.getRegister(registerName);
4771
+ if (registerName == ':') {
4772
+ // Read-only register containing last Ex command.
4773
+ if (register.keyBuffer[0]) {
4774
+ exCommandDispatcher.processCommand(cm, register.keyBuffer[0]);
4775
+ }
4776
+ macroModeState.isPlaying = false;
4777
+ return;
4778
+ }
4782
4779
  var keyBuffer = register.keyBuffer;
4783
4780
  var imc = 0;
4784
4781
  macroModeState.isPlaying = true;