codemirror-rails 4.8 → 4.9

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -6
  3. data/lib/codemirror/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/codemirror.js +289 -184
  5. data/vendor/assets/javascripts/codemirror/addons/dialog/dialog.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/addons/display/panel.js +94 -0
  7. data/vendor/assets/javascripts/codemirror/addons/edit/continuelist.js +4 -4
  8. data/vendor/assets/javascripts/codemirror/addons/hint/anyword-hint.js +1 -2
  9. data/vendor/assets/javascripts/codemirror/addons/hint/css-hint.js +1 -1
  10. data/vendor/assets/javascripts/codemirror/addons/hint/html-hint.js +1 -1
  11. data/vendor/assets/javascripts/codemirror/addons/hint/javascript-hint.js +8 -3
  12. data/vendor/assets/javascripts/codemirror/addons/hint/show-hint.js +1 -1
  13. data/vendor/assets/javascripts/codemirror/addons/hint/sql-hint.js +7 -4
  14. data/vendor/assets/javascripts/codemirror/addons/hint/xml-hint.js +3 -4
  15. data/vendor/assets/javascripts/codemirror/addons/merge/merge.js +170 -63
  16. data/vendor/assets/javascripts/codemirror/addons/mode/simple.js +11 -8
  17. data/vendor/assets/javascripts/codemirror/addons/scroll/annotatescrollbar.js +76 -0
  18. data/vendor/assets/javascripts/codemirror/addons/scroll/simplescrollbars.js +139 -0
  19. data/vendor/assets/javascripts/codemirror/addons/search/matchesonscrollbar.js +90 -0
  20. data/vendor/assets/javascripts/codemirror/addons/search/search.js +9 -4
  21. data/vendor/assets/javascripts/codemirror/addons/tern/tern.js +5 -3
  22. data/vendor/assets/javascripts/codemirror/keymaps/emacs.js +25 -7
  23. data/vendor/assets/javascripts/codemirror/keymaps/vim.js +181 -109
  24. data/vendor/assets/javascripts/codemirror/modes/coffeescript.js +2 -2
  25. data/vendor/assets/javascripts/codemirror/modes/commonlisp.js +5 -3
  26. data/vendor/assets/javascripts/codemirror/modes/cypher.js +1 -1
  27. data/vendor/assets/javascripts/codemirror/modes/dart.js +50 -0
  28. data/vendor/assets/javascripts/codemirror/modes/dockerfile.js +5 -9
  29. data/vendor/assets/javascripts/codemirror/modes/ebnf.js +195 -0
  30. data/vendor/assets/javascripts/codemirror/modes/javascript.js +2 -0
  31. data/vendor/assets/javascripts/codemirror/modes/markdown.js +3 -3
  32. data/vendor/assets/javascripts/codemirror/modes/puppet.js +2 -2
  33. data/vendor/assets/javascripts/codemirror/modes/shell.js +2 -1
  34. data/vendor/assets/javascripts/codemirror/modes/soy.js +198 -0
  35. data/vendor/assets/javascripts/codemirror/modes/spreadsheet.js +109 -0
  36. data/vendor/assets/javascripts/codemirror/modes/stex.js +4 -6
  37. data/vendor/assets/javascripts/codemirror/modes/textile.js +392 -476
  38. data/vendor/assets/javascripts/codemirror/modes/turtle.js +3 -1
  39. data/vendor/assets/stylesheets/codemirror.css +2 -11
  40. data/vendor/assets/stylesheets/codemirror/addons/merge/merge.css +14 -0
  41. data/vendor/assets/stylesheets/codemirror/addons/scroll/simplescrollbars.css +66 -0
  42. data/vendor/assets/stylesheets/codemirror/addons/search/matchesonscrollbar.css +8 -0
  43. data/vendor/assets/stylesheets/codemirror/themes/tomorrow-night-bright.css +35 -0
  44. data/vendor/assets/stylesheets/codemirror/themes/zenburn.css +37 -0
  45. metadata +14 -3
  46. data/vendor/assets/javascripts/codemirror/addons/hint/python-hint.js +0 -102
@@ -11,9 +11,9 @@
11
11
  })(function(CodeMirror) {
12
12
  "use strict";
13
13
 
14
- CodeMirror.defineSimpleMode = function(name, states, props) {
14
+ CodeMirror.defineSimpleMode = function(name, states) {
15
15
  CodeMirror.defineMode(name, function(config) {
16
- return CodeMirror.simpleMode(config, states, props);
16
+ return CodeMirror.simpleMode(config, states);
17
17
  });
18
18
  };
19
19
 
@@ -194,12 +194,15 @@
194
194
  var pos = state.indent.length - 1, rules = states[state.state];
195
195
  scan: for (;;) {
196
196
  for (var i = 0; i < rules.length; i++) {
197
- var rule = rules[i], m = rule.regex.exec(textAfter);
198
- if (m && m[0]) {
199
- if (rule.data.dedent && rule.data.dedentIfLineStart !== false) pos--;
200
- if (rule.next || rule.push) rules = states[rule.next || rule.push];
201
- textAfter = textAfter.slice(m[0].length);
202
- continue scan;
197
+ var rule = rules[i];
198
+ if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
199
+ var m = rule.regex.exec(textAfter);
200
+ if (m && m[0]) {
201
+ pos--;
202
+ if (rule.next || rule.push) rules = states[rule.next || rule.push];
203
+ textAfter = textAfter.slice(m[0].length);
204
+ continue scan;
205
+ }
203
206
  }
204
207
  }
205
208
  break;
@@ -0,0 +1,76 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ CodeMirror.defineExtension("annotateScrollbar", function(className) {
15
+ return new Annotation(this, className);
16
+ });
17
+
18
+ function Annotation(cm, className) {
19
+ this.cm = cm;
20
+ this.className = className;
21
+ this.annotations = [];
22
+ this.div = cm.getWrapperElement().appendChild(document.createElement("div"));
23
+ this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";
24
+ this.computeScale();
25
+
26
+ var self = this;
27
+ cm.on("refresh", this.resizeHandler = function(){
28
+ if (self.computeScale()) self.redraw();
29
+ });
30
+ }
31
+
32
+ Annotation.prototype.computeScale = function() {
33
+ var cm = this.cm;
34
+ var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight) /
35
+ cm.heightAtLine(cm.lastLine() + 1, "local");
36
+ if (hScale != this.hScale) {
37
+ this.hScale = hScale;
38
+ return true;
39
+ }
40
+ };
41
+
42
+ Annotation.prototype.update = function(annotations) {
43
+ this.annotations = annotations;
44
+ this.redraw();
45
+ };
46
+
47
+ Annotation.prototype.redraw = function() {
48
+ var cm = this.cm, hScale = this.hScale;
49
+ if (!cm.display.barWidth) return;
50
+
51
+ var frag = document.createDocumentFragment(), anns = this.annotations;
52
+ for (var i = 0, nextTop; i < anns.length; i++) {
53
+ var ann = anns[i];
54
+ var top = nextTop || cm.charCoords(ann.from, "local").top * hScale;
55
+ var bottom = cm.charCoords(ann.to, "local").bottom * hScale;
56
+ while (i < anns.length - 1) {
57
+ nextTop = cm.charCoords(anns[i + 1].from, "local").top * hScale;
58
+ if (nextTop > bottom + .9) break;
59
+ ann = anns[++i];
60
+ bottom = cm.charCoords(ann.to, "local").bottom * hScale;
61
+ }
62
+ var height = Math.max(bottom - top, 3);
63
+
64
+ var elt = frag.appendChild(document.createElement("div"));
65
+ elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: " + top + "px; height: " + height + "px";
66
+ elt.className = this.className;
67
+ }
68
+ this.div.textContent = "";
69
+ this.div.appendChild(frag);
70
+ };
71
+
72
+ Annotation.prototype.clear = function() {
73
+ this.cm.off("refresh", this.resizeHandler);
74
+ this.div.parentNode.removeChild(this.div);
75
+ };
76
+ });
@@ -0,0 +1,139 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ function Bar(cls, orientation, scroll) {
15
+ this.orientation = orientation;
16
+ this.scroll = scroll;
17
+ this.screen = this.total = this.size = 1;
18
+ this.pos = 0;
19
+
20
+ this.node = document.createElement("div");
21
+ this.node.className = cls + "-" + orientation;
22
+ this.inner = this.node.appendChild(document.createElement("div"));
23
+
24
+ var self = this;
25
+ CodeMirror.on(this.inner, "mousedown", function(e) {
26
+ if (e.which != 1) return;
27
+ CodeMirror.e_preventDefault(e);
28
+ var axis = self.orientation == "horizontal" ? "pageX" : "pageY";
29
+ var start = e[axis], startpos = self.pos;
30
+ function move(e) {
31
+ if (e.which != 1) {
32
+ CodeMirror.off(document, "mousemove", move);
33
+ return;
34
+ }
35
+ self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));
36
+ }
37
+ CodeMirror.on(document, "mousemove", move);
38
+ });
39
+
40
+ CodeMirror.on(this.node, "click", function(e) {
41
+ CodeMirror.e_preventDefault(e);
42
+ var innerBox = self.inner.getBoundingClientRect(), where;
43
+ if (self.orientation == "horizontal")
44
+ where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;
45
+ else
46
+ where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;
47
+ self.moveTo(self.pos + where * self.screen);
48
+ });
49
+
50
+ function onWheel(e) {
51
+ var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];
52
+ var oldPos = self.pos;
53
+ self.moveTo(self.pos + moved);
54
+ if (self.pos != oldPos) CodeMirror.e_preventDefault(e);
55
+ }
56
+ CodeMirror.on(this.node, "mousewheel", onWheel);
57
+ CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
58
+ }
59
+
60
+ Bar.prototype.moveTo = function(pos, update) {
61
+ if (pos < 0) pos = 0;
62
+ if (pos > this.total - this.screen) pos = this.total - this.screen;
63
+ if (pos == this.pos) return;
64
+ this.pos = pos;
65
+ this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
66
+ (pos * (this.size / this.total)) + "px";
67
+ if (update !== false) this.scroll(pos, this.orientation);
68
+ };
69
+
70
+ Bar.prototype.update = function(scrollSize, clientSize, barSize) {
71
+ this.screen = clientSize;
72
+ this.total = scrollSize;
73
+ this.size = barSize;
74
+
75
+ // FIXME clip to min size?
76
+ this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
77
+ this.screen * (this.size / this.total) + "px";
78
+ this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
79
+ this.pos * (this.size / this.total) + "px";
80
+ };
81
+
82
+ function SimpleScrollbars(cls, place, scroll) {
83
+ this.addClass = cls;
84
+ this.horiz = new Bar(cls, "horizontal", scroll);
85
+ place(this.horiz.node);
86
+ this.vert = new Bar(cls, "vertical", scroll);
87
+ place(this.vert.node);
88
+ this.width = null;
89
+ }
90
+
91
+ SimpleScrollbars.prototype.update = function(measure) {
92
+ if (this.width == null) {
93
+ var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;
94
+ if (style) this.width = parseInt(style.height);
95
+ }
96
+ var width = this.width || 0;
97
+
98
+ var needsH = measure.scrollWidth > measure.clientWidth + 1;
99
+ var needsV = measure.scrollHeight > measure.clientHeight + 1;
100
+ this.vert.node.style.display = needsV ? "block" : "none";
101
+ this.horiz.node.style.display = needsH ? "block" : "none";
102
+
103
+ if (needsV) {
104
+ this.vert.update(measure.scrollHeight, measure.clientHeight,
105
+ measure.viewHeight - (needsH ? width : 0));
106
+ this.vert.node.style.display = "block";
107
+ this.vert.node.style.bottom = needsH ? width + "px" : "0";
108
+ }
109
+ if (needsH) {
110
+ this.horiz.update(measure.scrollWidth, measure.clientWidth,
111
+ measure.viewWidth - (needsV ? width : 0) - measure.barLeft);
112
+ this.horiz.node.style.right = needsV ? width + "px" : "0";
113
+ this.horiz.node.style.left = measure.barLeft + "px";
114
+ }
115
+
116
+ return {right: needsV ? width : 0, bottom: needsH ? width : 0};
117
+ };
118
+
119
+ SimpleScrollbars.prototype.setScrollTop = function(pos) {
120
+ this.vert.moveTo(pos, false);
121
+ };
122
+
123
+ SimpleScrollbars.prototype.setScrollLeft = function(pos) {
124
+ this.horiz.moveTo(pos, false);
125
+ };
126
+
127
+ SimpleScrollbars.prototype.clear = function() {
128
+ var parent = this.horiz.node.parentNode;
129
+ parent.removeChild(this.horiz.node);
130
+ parent.removeChild(this.vert.node);
131
+ };
132
+
133
+ CodeMirror.scrollbarModel.simple = function(place, scroll) {
134
+ return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);
135
+ };
136
+ CodeMirror.scrollbarModel.overlay = function(place, scroll) {
137
+ return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);
138
+ };
139
+ });
@@ -0,0 +1,90 @@
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, className) {
15
+ return new SearchAnnotation(this, query, caseFold, className);
16
+ });
17
+
18
+ function SearchAnnotation(cm, query, caseFold, className) {
19
+ this.cm = cm;
20
+ this.annotation = cm.annotateScrollbar(className || "CodeMirror-search-match");
21
+ this.query = query;
22
+ this.caseFold = caseFold;
23
+ this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};
24
+ this.matches = [];
25
+ this.update = null;
26
+
27
+ this.findMatches();
28
+ this.annotation.update(this.matches);
29
+
30
+ var self = this;
31
+ cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); });
32
+ }
33
+
34
+ var MAX_MATCHES = 1000;
35
+
36
+ SearchAnnotation.prototype.findMatches = function() {
37
+ if (!this.gap) return;
38
+ for (var i = 0; i < this.matches.length; i++) {
39
+ var match = this.matches[i];
40
+ if (match.from.line >= this.gap.to) break;
41
+ if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
42
+ }
43
+ var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold);
44
+ while (cursor.findNext()) {
45
+ var match = {from: cursor.from(), to: cursor.to()};
46
+ if (match.from.line >= this.gap.to) break;
47
+ this.matches.splice(i++, 0, match);
48
+ if (this.matches.length > MAX_MATCHES) break;
49
+ }
50
+ this.gap = null;
51
+ };
52
+
53
+ function offsetLine(line, changeStart, sizeChange) {
54
+ if (line <= changeStart) return line;
55
+ return Math.max(changeStart, line + sizeChange);
56
+ }
57
+
58
+ SearchAnnotation.prototype.onChange = function(change) {
59
+ var startLine = change.from.line;
60
+ var endLine = CodeMirror.changeEnd(change).line;
61
+ var sizeChange = endLine - change.to.line;
62
+ if (this.gap) {
63
+ this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line);
64
+ this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line);
65
+ } else {
66
+ this.gap = {from: change.from.line, to: endLine + 1};
67
+ }
68
+
69
+ if (sizeChange) for (var i = 0; i < this.matches.length; i++) {
70
+ var match = this.matches[i];
71
+ var newFrom = offsetLine(match.from.line, startLine, sizeChange);
72
+ if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch);
73
+ var newTo = offsetLine(match.to.line, startLine, sizeChange);
74
+ if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch);
75
+ }
76
+ clearTimeout(this.update);
77
+ var self = this;
78
+ this.update = setTimeout(function() { self.updateAfterChange(); }, 250);
79
+ };
80
+
81
+ SearchAnnotation.prototype.updateAfterChange = function() {
82
+ this.findMatches();
83
+ this.annotation.update(this.matches);
84
+ };
85
+
86
+ SearchAnnotation.prototype.clear = function() {
87
+ this.cm.off("change", this.changeHandler);
88
+ this.annotation.clear();
89
+ };
90
+ });
@@ -63,11 +63,11 @@
63
63
  function parseQuery(query) {
64
64
  var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
65
65
  if (isRE) {
66
- query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i");
67
- if (query.test("")) query = /x^/;
68
- } else if (query == "") {
69
- query = /x^/;
66
+ try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
67
+ catch(e) {} // Not a regular expression after all, do a string search
70
68
  }
69
+ if (typeof query == "string" ? query == "" : query.test(""))
70
+ query = /x^/;
71
71
  return query;
72
72
  }
73
73
  var queryDialog =
@@ -82,6 +82,10 @@
82
82
  cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
83
83
  state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
84
84
  cm.addOverlay(state.overlay);
85
+ if (cm.showMatchesOnScrollbar) {
86
+ if (state.annotate) { state.annotate.clear(); state.annotate = null; }
87
+ state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
88
+ }
85
89
  state.posFrom = state.posTo = cm.getCursor();
86
90
  findNext(cm, rev);
87
91
  });
@@ -103,6 +107,7 @@
103
107
  if (!state.query) return;
104
108
  state.query = null;
105
109
  cm.removeOverlay(state.overlay);
110
+ if (state.annotate) { state.annotate.clear(); state.annotate = null; }
106
111
  });}
107
112
 
108
113
  var replaceQueryDialog =
@@ -106,7 +106,9 @@
106
106
  cm.showHint({hint: this.getHint});
107
107
  },
108
108
 
109
- showType: function(cm, pos, c) { showType(this, cm, pos, c); },
109
+ showType: function(cm, pos, c) { showContextInfo(this, cm, pos, "type", c); },
110
+
111
+ showDocs: function(cm, pos, c) { showContextInfo(this, cm, pos, "documentation", c); },
110
112
 
111
113
  updateArgHints: function(cm) { updateArgHints(this, cm); },
112
114
 
@@ -239,8 +241,8 @@
239
241
 
240
242
  // Type queries
241
243
 
242
- function showType(ts, cm, pos, c) {
243
- ts.request(cm, "type", function(error, data) {
244
+ function showContextInfo(ts, cm, pos, queryName, c) {
245
+ ts.request(cm, queryName, function(error, data) {
244
246
  if (error) return showError(ts, cm, error);
245
247
  if (ts.options.typeTip) {
246
248
  var tip = ts.options.typeTip(data);
@@ -132,8 +132,8 @@
132
132
  };
133
133
  }
134
134
 
135
- function findEnd(cm, by, dir) {
136
- var pos = cm.getCursor(), prefix = getPrefix(cm);
135
+ function findEnd(cm, pos, by, dir) {
136
+ var prefix = getPrefix(cm);
137
137
  if (prefix < 0) { dir = -dir; prefix = -prefix; }
138
138
  for (var i = 0; i < prefix; ++i) {
139
139
  var newPos = by(cm, pos, dir);
@@ -145,14 +145,31 @@
145
145
 
146
146
  function move(by, dir) {
147
147
  var f = function(cm) {
148
- cm.extendSelection(findEnd(cm, by, dir));
148
+ cm.extendSelection(findEnd(cm, cm.getCursor(), by, dir));
149
149
  };
150
150
  f.motion = true;
151
151
  return f;
152
152
  }
153
153
 
154
154
  function killTo(cm, by, dir) {
155
- kill(cm, cm.getCursor(), findEnd(cm, by, dir), true);
155
+ var selections = cm.listSelections(), cursor;
156
+ var i = selections.length;
157
+ while (i--) {
158
+ cursor = selections[i].head;
159
+ kill(cm, cursor, findEnd(cm, cursor, by, dir), true);
160
+ }
161
+ }
162
+
163
+ function killRegion(cm) {
164
+ if (cm.somethingSelected()) {
165
+ var selections = cm.listSelections(), selection;
166
+ var i = selections.length;
167
+ while (i--) {
168
+ selection = selections[i];
169
+ kill(cm, selection.anchor, selection.head);
170
+ }
171
+ return true;
172
+ }
156
173
  }
157
174
 
158
175
  function addPrefix(cm, digit) {
@@ -283,9 +300,9 @@
283
300
  "Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1),
284
301
  "Right": move(byChar, 1), "Left": move(byChar, -1),
285
302
  "Ctrl-D": function(cm) { killTo(cm, byChar, 1); },
286
- "Delete": function(cm) { killTo(cm, byChar, 1); },
303
+ "Delete": function(cm) { killRegion(cm) || killTo(cm, byChar, 1); },
287
304
  "Ctrl-H": function(cm) { killTo(cm, byChar, -1); },
288
- "Backspace": function(cm) { killTo(cm, byChar, -1); },
305
+ "Backspace": function(cm) { killRegion(cm) || killTo(cm, byChar, -1); },
289
306
 
290
307
  "Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1),
291
308
  "Alt-D": function(cm) { killTo(cm, byWord, 1); },
@@ -309,7 +326,8 @@
309
326
  "Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1),
310
327
 
311
328
  "Shift-Ctrl-Alt-2": function(cm) {
312
- cm.setSelection(findEnd(cm, byExpr, 1), cm.getCursor());
329
+ var cursor = cm.getCursor();
330
+ cm.setSelection(findEnd(cm, cursor, byExpr, 1), cursor);
313
331
  },
314
332
  "Ctrl-Alt-T": function(cm) {
315
333
  var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1);