formagic 0.1.0 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/formagic/form.coffee +31 -11
  3. data/app/assets/javascripts/formagic/inputs/checkbox.coffee +1 -0
  4. data/app/assets/javascripts/formagic/inputs/date.coffee +28 -3
  5. data/app/assets/javascripts/formagic/inputs/datetime.coffee +30 -2
  6. data/app/assets/javascripts/formagic/inputs/document.coffee +110 -0
  7. data/app/assets/javascripts/formagic/inputs/documents.coffee +39 -13
  8. data/app/assets/javascripts/formagic/inputs/documents_reorder.coffee +1 -1
  9. data/app/assets/javascripts/formagic/inputs/file.coffee +3 -0
  10. data/app/assets/javascripts/formagic/inputs/html.coffee +1 -0
  11. data/app/assets/javascripts/formagic/inputs/redactor.coffee +1 -0
  12. data/app/assets/javascripts/formagic/inputs/redactor_character.coffee +16 -14
  13. data/app/assets/javascripts/formagic/inputs/select2.coffee +1 -1
  14. data/app/assets/javascripts/formagic/inputs/string.coffee +5 -4
  15. data/app/assets/javascripts/formagic/inputs/text.coffee +4 -3
  16. data/app/assets/javascripts/formagic/inputs/url.coffee +37 -0
  17. data/app/assets/javascripts/formagic.coffee +2 -1
  18. data/app/assets/javascripts/vendor/ace.js +811 -577
  19. data/app/assets/javascripts/vendor/mode-html.js +24 -25
  20. data/app/assets/javascripts/vendor/mode-markdown.js +25 -26
  21. data/app/assets/javascripts/vendor/redactor.table.js +338 -0
  22. data/app/assets/stylesheets/formagic/date.scss +1 -0
  23. data/app/assets/stylesheets/formagic/file.scss +7 -0
  24. data/app/assets/stylesheets/formagic/form.scss +15 -10
  25. data/app/assets/stylesheets/formagic/image.scss +4 -0
  26. data/app/assets/stylesheets/formagic/label.scss +27 -0
  27. data/app/assets/stylesheets/formagic/nested-form.scss +3 -3
  28. data/app/assets/stylesheets/formagic/select2.scss +19 -1
  29. data/app/assets/stylesheets/formagic.scss +2 -1
  30. data/lib/formagic/version.rb +1 -1
  31. metadata +6 -3
  32. /data/app/assets/stylesheets/formagic/{redactor.scss → redactor1.scss} +0 -0
@@ -1035,6 +1035,9 @@ exports.importCssString = function importCssString(cssText, id, doc) {
1035
1035
 
1036
1036
  var style;
1037
1037
 
1038
+ if (id)
1039
+ cssText += "\n/*# sourceURL=ace/css/" + id + " */";
1040
+
1038
1041
  if (doc.createStyleSheet) {
1039
1042
  style = doc.createStyleSheet();
1040
1043
  style.cssText = cssText;
@@ -1081,42 +1084,6 @@ exports.getInnerHeight = function(element) {
1081
1084
  );
1082
1085
  };
1083
1086
 
1084
-
1085
- if (typeof document == "undefined")
1086
- return;
1087
-
1088
- if (window.pageYOffset !== undefined) {
1089
- exports.getPageScrollTop = function() {
1090
- return window.pageYOffset;
1091
- };
1092
-
1093
- exports.getPageScrollLeft = function() {
1094
- return window.pageXOffset;
1095
- };
1096
- }
1097
- else {
1098
- exports.getPageScrollTop = function() {
1099
- return document.body.scrollTop;
1100
- };
1101
-
1102
- exports.getPageScrollLeft = function() {
1103
- return document.body.scrollLeft;
1104
- };
1105
- }
1106
-
1107
- if (window.getComputedStyle)
1108
- exports.computedStyle = function(element, style) {
1109
- if (style)
1110
- return (window.getComputedStyle(element, "") || {})[style] || "";
1111
- return window.getComputedStyle(element, "") || {};
1112
- };
1113
- else
1114
- exports.computedStyle = function(element, style) {
1115
- if (style)
1116
- return element.currentStyle[style];
1117
- return element.currentStyle;
1118
- };
1119
-
1120
1087
  exports.scrollbarWidth = function(document) {
1121
1088
  var inner = exports.createElement("ace_inner");
1122
1089
  inner.style.width = "100%";
@@ -1153,6 +1120,43 @@ exports.scrollbarWidth = function(document) {
1153
1120
 
1154
1121
  return noScrollbar-withScrollbar;
1155
1122
  };
1123
+
1124
+ if (typeof document == "undefined") {
1125
+ exports.importCssString = function() {};
1126
+ return;
1127
+ }
1128
+
1129
+ if (window.pageYOffset !== undefined) {
1130
+ exports.getPageScrollTop = function() {
1131
+ return window.pageYOffset;
1132
+ };
1133
+
1134
+ exports.getPageScrollLeft = function() {
1135
+ return window.pageXOffset;
1136
+ };
1137
+ }
1138
+ else {
1139
+ exports.getPageScrollTop = function() {
1140
+ return document.body.scrollTop;
1141
+ };
1142
+
1143
+ exports.getPageScrollLeft = function() {
1144
+ return document.body.scrollLeft;
1145
+ };
1146
+ }
1147
+
1148
+ if (window.getComputedStyle)
1149
+ exports.computedStyle = function(element, style) {
1150
+ if (style)
1151
+ return (window.getComputedStyle(element, "") || {})[style] || "";
1152
+ return window.getComputedStyle(element, "") || {};
1153
+ };
1154
+ else
1155
+ exports.computedStyle = function(element, style) {
1156
+ if (style)
1157
+ return element.currentStyle[style];
1158
+ return element.currentStyle;
1159
+ };
1156
1160
  exports.setInnerHtml = function(el, innerHtml) {
1157
1161
  var element = el.cloneNode(false);//document.createElement("div");
1158
1162
  element.innerHTML = innerHtml;
@@ -1282,8 +1286,8 @@ var Keys = (function() {
1282
1286
  73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o',
1283
1287
  80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v',
1284
1288
  87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.',
1285
- 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', 219: '[',
1286
- 220: '\\',221: ']', 222: '\''
1289
+ 186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`',
1290
+ 219: '[', 220: '\\',221: ']', 222: '\''
1287
1291
  }
1288
1292
  };
1289
1293
  var name, i;
@@ -1451,6 +1455,29 @@ exports.capture = function(el, eventHandler, releaseCaptureHandler) {
1451
1455
  return onMouseUp;
1452
1456
  };
1453
1457
 
1458
+ exports.addTouchMoveListener = function (el, callback) {
1459
+ if ("ontouchmove" in el) {
1460
+ var startx, starty;
1461
+ exports.addListener(el, "touchstart", function (e) {
1462
+ var touchObj = e.changedTouches[0];
1463
+ startx = touchObj.clientX;
1464
+ starty = touchObj.clientY;
1465
+ });
1466
+ exports.addListener(el, "touchmove", function (e) {
1467
+ var factor = 1,
1468
+ touchObj = e.changedTouches[0];
1469
+
1470
+ e.wheelX = -(touchObj.clientX - startx) / factor;
1471
+ e.wheelY = -(touchObj.clientY - starty) / factor;
1472
+
1473
+ startx = touchObj.clientX;
1474
+ starty = touchObj.clientY;
1475
+
1476
+ callback(e);
1477
+ });
1478
+ }
1479
+ };
1480
+
1454
1481
  exports.addMouseWheelListener = function(el, callback) {
1455
1482
  if ("onmousewheel" in el) {
1456
1483
  exports.addListener(el, "mousewheel", function(e) {
@@ -1580,7 +1607,7 @@ function normalizeCommandKeys(callback, e, keyCode) {
1580
1607
  if (pressedKeys[keyCode] == 1)
1581
1608
  ts = e.timeStamp;
1582
1609
  } else if (keyCode === 18 && hashId === 3 && location === 2) {
1583
- var dt = e.timestamp - ts;
1610
+ var dt = e.timeStamp - ts;
1584
1611
  if (dt < 50)
1585
1612
  pressedKeys.altGr = true;
1586
1613
  }
@@ -1652,15 +1679,16 @@ exports.addCommandKeyListener = function(el, callback) {
1652
1679
  });
1653
1680
 
1654
1681
  if (!pressedKeys) {
1655
- pressedKeys = Object.create(null);
1656
- addListener(window, "focus", function(e) {
1657
- pressedKeys = Object.create(null);
1658
- });
1682
+ resetPressedKeys();
1683
+ addListener(window, "focus", resetPressedKeys);
1659
1684
  }
1660
1685
  }
1661
1686
  };
1687
+ function resetPressedKeys(e) {
1688
+ pressedKeys = Object.create(null);
1689
+ }
1662
1690
 
1663
- if (window.postMessage && !useragent.isOldIE) {
1691
+ if (typeof window == "object" && window.postMessage && !useragent.isOldIE) {
1664
1692
  var postMessageId = 1;
1665
1693
  exports.nextTick = function(callback, win) {
1666
1694
  win = win || window;
@@ -1677,11 +1705,11 @@ if (window.postMessage && !useragent.isOldIE) {
1677
1705
  }
1678
1706
 
1679
1707
 
1680
- exports.nextFrame = window.requestAnimationFrame ||
1681
- window.mozRequestAnimationFrame ||
1682
- window.webkitRequestAnimationFrame ||
1683
- window.msRequestAnimationFrame ||
1684
- window.oRequestAnimationFrame;
1708
+ exports.nextFrame = typeof window == "object" && (window.requestAnimationFrame
1709
+ || window.mozRequestAnimationFrame
1710
+ || window.webkitRequestAnimationFrame
1711
+ || window.msRequestAnimationFrame
1712
+ || window.oRequestAnimationFrame);
1685
1713
 
1686
1714
  if (exports.nextFrame)
1687
1715
  exports.nextFrame = exports.nextFrame.bind(window);
@@ -1744,20 +1772,24 @@ exports.copyArray = function(array){
1744
1772
  return copy;
1745
1773
  };
1746
1774
 
1747
- exports.deepCopy = function (obj) {
1775
+ exports.deepCopy = function deepCopy(obj) {
1748
1776
  if (typeof obj !== "object" || !obj)
1749
1777
  return obj;
1778
+ var copy;
1779
+ if (Array.isArray(obj)) {
1780
+ copy = [];
1781
+ for (var key = 0; key < obj.length; key++) {
1782
+ copy[key] = deepCopy(obj[key]);
1783
+ }
1784
+ return copy;
1785
+ }
1750
1786
  var cons = obj.constructor;
1751
1787
  if (cons === RegExp)
1752
1788
  return obj;
1753
1789
 
1754
- var copy = cons();
1790
+ copy = cons();
1755
1791
  for (var key in obj) {
1756
- if (typeof obj[key] === "object") {
1757
- copy[key] = exports.deepCopy(obj[key]);
1758
- } else {
1759
- copy[key] = obj[key];
1760
- }
1792
+ copy[key] = deepCopy(obj[key]);
1761
1793
  }
1762
1794
  return copy;
1763
1795
  };
@@ -1922,14 +1954,20 @@ var TextInput = function(parentNode, host) {
1922
1954
  resetSelection();
1923
1955
  });
1924
1956
  this.focus = function() {
1957
+ if (tempStyle) return text.focus();
1958
+ var top = text.style.top;
1925
1959
  text.style.position = "fixed";
1926
1960
  text.style.top = "-1000px";
1927
1961
  text.focus();
1928
1962
  setTimeout(function() {
1929
1963
  text.style.position = "";
1964
+ if (text.style.top == "-1000px")
1965
+ text.style.top = top;
1930
1966
  }, 0);
1931
1967
  };
1932
- this.blur = function() { text.blur(); };
1968
+ this.blur = function() {
1969
+ text.blur();
1970
+ };
1933
1971
  this.isFocused = function() {
1934
1972
  return isFocused;
1935
1973
  };
@@ -2134,7 +2172,7 @@ var TextInput = function(parentNode, host) {
2134
2172
  var data = handleClipboardData(e);
2135
2173
  if (typeof data == "string") {
2136
2174
  if (data)
2137
- host.onPaste(data);
2175
+ host.onPaste(data, e);
2138
2176
  if (useragent.isIE)
2139
2177
  setTimeout(resetSelection);
2140
2178
  event.preventDefault(e);
@@ -2300,7 +2338,7 @@ var TextInput = function(parentNode, host) {
2300
2338
  this.onContextMenuClose = onContextMenuClose;
2301
2339
  var closeTimeout;
2302
2340
  function onContextMenuClose() {
2303
- clearTimeout(closeTimeout)
2341
+ clearTimeout(closeTimeout);
2304
2342
  closeTimeout = setTimeout(function () {
2305
2343
  if (tempStyle) {
2306
2344
  text.style.cssText = tempStyle;
@@ -2342,6 +2380,7 @@ function DefaultHandlers(mouseHandler) {
2342
2380
  editor.setDefaultHandler("tripleclick", this.onTripleClick.bind(mouseHandler));
2343
2381
  editor.setDefaultHandler("quadclick", this.onQuadClick.bind(mouseHandler));
2344
2382
  editor.setDefaultHandler("mousewheel", this.onMouseWheel.bind(mouseHandler));
2383
+ editor.setDefaultHandler("touchmove", this.onTouchMove.bind(mouseHandler));
2345
2384
 
2346
2385
  var exports = ["select", "startSelect", "selectEnd", "selectAllEnd", "selectByWordsEnd",
2347
2386
  "selectByLinesEnd", "dragWait", "dragWaitEnd", "focusWait"];
@@ -2543,6 +2582,19 @@ function DefaultHandlers(mouseHandler) {
2543
2582
  return ev.stop();
2544
2583
  }
2545
2584
  };
2585
+
2586
+ this.onTouchMove = function (ev) {
2587
+ var t = ev.domEvent.timeStamp;
2588
+ var dt = t - (this.$lastScrollTime || 0);
2589
+
2590
+ var editor = this.editor;
2591
+ var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
2592
+ if (isScrolable || dt < 200) {
2593
+ this.$lastScrollTime = t;
2594
+ editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);
2595
+ return ev.stop();
2596
+ }
2597
+ };
2546
2598
 
2547
2599
  }).call(DefaultHandlers.prototype);
2548
2600
 
@@ -3537,7 +3589,7 @@ var AppConfig = require("./lib/app_config").AppConfig;
3537
3589
  module.exports = exports = new AppConfig();
3538
3590
 
3539
3591
  var global = (function() {
3540
- return this;
3592
+ return this || typeof window != "undefined" && window;
3541
3593
  })();
3542
3594
 
3543
3595
  var options = {
@@ -3729,6 +3781,7 @@ var MouseHandler = function(editor) {
3729
3781
  }
3730
3782
  }
3731
3783
  event.addMouseWheelListener(editor.container, this.onMouseWheel.bind(this, "mousewheel"));
3784
+ event.addTouchMoveListener(editor.container, this.onTouchMove.bind(this, "touchmove"));
3732
3785
 
3733
3786
  var gutterEl = editor.renderer.$gutter;
3734
3787
  event.addListener(gutterEl, "mousedown", this.onMouseEvent.bind(this, "guttermousedown"));
@@ -3780,6 +3833,14 @@ var MouseHandler = function(editor) {
3780
3833
 
3781
3834
  this.editor._emit(name, mouseEvent);
3782
3835
  };
3836
+
3837
+ this.onTouchMove = function (name, e) {
3838
+ var mouseEvent = new MouseEvent(e, this.editor);
3839
+ mouseEvent.speed = 1;//this.$scrollSpeed * 2;
3840
+ mouseEvent.wheelX = e.wheelX;
3841
+ mouseEvent.wheelY = e.wheelY;
3842
+ this.editor._emit(name, mouseEvent);
3843
+ };
3783
3844
 
3784
3845
  this.setState = function(state) {
3785
3846
  this.state = state;
@@ -4851,7 +4912,7 @@ var Selection = function(session) {
4851
4912
  this.toSingleRange(data[0]);
4852
4913
  for (var i = data.length; i--; ) {
4853
4914
  var r = Range.fromPoints(data[i].start, data[i].end);
4854
- if (data.isBackwards)
4915
+ if (data[i].isBackwards)
4855
4916
  r.cursor = r.start;
4856
4917
  this.addRange(r, true);
4857
4918
  }
@@ -5566,6 +5627,9 @@ var TokenIterator = function(session, initialRow, initialColumn) {
5566
5627
 
5567
5628
  return column;
5568
5629
  };
5630
+ this.getCurrentTokenPosition = function() {
5631
+ return {row: this.$row, column: this.getCurrentTokenColumn()};
5632
+ };
5569
5633
 
5570
5634
  }).call(TokenIterator.prototype);
5571
5635
 
@@ -5925,6 +5989,71 @@ var Mode = function() {
5925
5989
  exports.Mode = Mode;
5926
5990
  });
5927
5991
 
5992
+ define("ace/apply_delta",["require","exports","module"], function(require, exports, module) {
5993
+ "use strict";
5994
+
5995
+ function throwDeltaError(delta, errorText){
5996
+ console.log("Invalid Delta:", delta);
5997
+ throw "Invalid Delta: " + errorText;
5998
+ }
5999
+
6000
+ function positionInDocument(docLines, position) {
6001
+ return position.row >= 0 && position.row < docLines.length &&
6002
+ position.column >= 0 && position.column <= docLines[position.row].length;
6003
+ }
6004
+
6005
+ function validateDelta(docLines, delta) {
6006
+ if (delta.action != "insert" && delta.action != "remove")
6007
+ throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
6008
+ if (!(delta.lines instanceof Array))
6009
+ throwDeltaError(delta, "delta.lines must be an Array");
6010
+ if (!delta.start || !delta.end)
6011
+ throwDeltaError(delta, "delta.start/end must be an present");
6012
+ var start = delta.start;
6013
+ if (!positionInDocument(docLines, delta.start))
6014
+ throwDeltaError(delta, "delta.start must be contained in document");
6015
+ var end = delta.end;
6016
+ if (delta.action == "remove" && !positionInDocument(docLines, end))
6017
+ throwDeltaError(delta, "delta.end must contained in document for 'remove' actions");
6018
+ var numRangeRows = end.row - start.row;
6019
+ var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));
6020
+ if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)
6021
+ throwDeltaError(delta, "delta.range must match delta lines");
6022
+ }
6023
+
6024
+ exports.applyDelta = function(docLines, delta, doNotValidate) {
6025
+
6026
+ var row = delta.start.row;
6027
+ var startColumn = delta.start.column;
6028
+ var line = docLines[row] || "";
6029
+ switch (delta.action) {
6030
+ case "insert":
6031
+ var lines = delta.lines;
6032
+ if (lines.length === 1) {
6033
+ docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
6034
+ } else {
6035
+ var args = [row, 1].concat(delta.lines);
6036
+ docLines.splice.apply(docLines, args);
6037
+ docLines[row] = line.substring(0, startColumn) + docLines[row];
6038
+ docLines[row + delta.lines.length - 1] += line.substring(startColumn);
6039
+ }
6040
+ break;
6041
+ case "remove":
6042
+ var endColumn = delta.end.column;
6043
+ var endRow = delta.end.row;
6044
+ if (row === endRow) {
6045
+ docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
6046
+ } else {
6047
+ docLines.splice(
6048
+ row, endRow - row + 1,
6049
+ line.substring(0, startColumn) + docLines[endRow].substring(endColumn)
6050
+ );
6051
+ }
6052
+ break;
6053
+ }
6054
+ }
6055
+ });
6056
+
5928
6057
  define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) {
5929
6058
  "use strict";
5930
6059
 
@@ -5951,70 +6080,46 @@ var Anchor = exports.Anchor = function(doc, row, column) {
5951
6080
  return this.document;
5952
6081
  };
5953
6082
  this.$insertRight = false;
5954
- this.onChange = function(e) {
5955
- var delta = e.data;
5956
- var range = delta.range;
5957
-
5958
- if (range.start.row == range.end.row && range.start.row != this.row)
5959
- return;
5960
-
5961
- if (range.start.row > this.row)
6083
+ this.onChange = function(delta) {
6084
+ if (delta.start.row == delta.end.row && delta.start.row != this.row)
5962
6085
  return;
5963
6086
 
5964
- if (range.start.row == this.row && range.start.column > this.column)
6087
+ if (delta.start.row > this.row)
5965
6088
  return;
5966
-
5967
- var row = this.row;
5968
- var column = this.column;
5969
- var start = range.start;
5970
- var end = range.end;
5971
-
5972
- if (delta.action === "insertText") {
5973
- if (start.row === row && start.column <= column) {
5974
- if (start.column === column && this.$insertRight) {
5975
- } else if (start.row === end.row) {
5976
- column += end.column - start.column;
5977
- } else {
5978
- column -= start.column;
5979
- row += end.row - start.row;
5980
- }
5981
- } else if (start.row !== end.row && start.row < row) {
5982
- row += end.row - start.row;
5983
- }
5984
- } else if (delta.action === "insertLines") {
5985
- if (start.row === row && column === 0 && this.$insertRight) {
5986
- }
5987
- else if (start.row <= row) {
5988
- row += end.row - start.row;
5989
- }
5990
- } else if (delta.action === "removeText") {
5991
- if (start.row === row && start.column < column) {
5992
- if (end.column >= column)
5993
- column = start.column;
5994
- else
5995
- column = Math.max(0, column - (end.column - start.column));
5996
-
5997
- } else if (start.row !== end.row && start.row < row) {
5998
- if (end.row === row)
5999
- column = Math.max(0, column - end.column) + start.column;
6000
- row -= (end.row - start.row);
6001
- } else if (end.row === row) {
6002
- row -= end.row - start.row;
6003
- column = Math.max(0, column - end.column) + start.column;
6004
- }
6005
- } else if (delta.action == "removeLines") {
6006
- if (start.row <= row) {
6007
- if (end.row <= row)
6008
- row -= end.row - start.row;
6009
- else {
6010
- row = start.row;
6011
- column = 0;
6012
- }
6013
- }
6014
- }
6015
-
6016
- this.setPosition(row, column, true);
6089
+
6090
+ var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight);
6091
+ this.setPosition(point.row, point.column, true);
6017
6092
  };
6093
+
6094
+ function $pointsInOrder(point1, point2, equalPointsInOrder) {
6095
+ var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column;
6096
+ return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter);
6097
+ }
6098
+
6099
+ function $getTransformedPoint(delta, point, moveIfEqual) {
6100
+ var deltaIsInsert = delta.action == "insert";
6101
+ var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row);
6102
+ var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);
6103
+ var deltaStart = delta.start;
6104
+ var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.
6105
+ if ($pointsInOrder(point, deltaStart, moveIfEqual)) {
6106
+ return {
6107
+ row: point.row,
6108
+ column: point.column
6109
+ };
6110
+ }
6111
+ if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {
6112
+ return {
6113
+ row: point.row + deltaRowShift,
6114
+ column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0)
6115
+ };
6116
+ }
6117
+
6118
+ return {
6119
+ row: deltaStart.row,
6120
+ column: deltaStart.column
6121
+ };
6122
+ }
6018
6123
  this.setPosition = function(row, column, noClip) {
6019
6124
  var pos;
6020
6125
  if (noClip) {
@@ -6074,22 +6179,23 @@ var Anchor = exports.Anchor = function(doc, row, column) {
6074
6179
 
6075
6180
  });
6076
6181
 
6077
- define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"], function(require, exports, module) {
6182
+ define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"], function(require, exports, module) {
6078
6183
  "use strict";
6079
6184
 
6080
6185
  var oop = require("./lib/oop");
6186
+ var applyDelta = require("./apply_delta").applyDelta;
6081
6187
  var EventEmitter = require("./lib/event_emitter").EventEmitter;
6082
6188
  var Range = require("./range").Range;
6083
6189
  var Anchor = require("./anchor").Anchor;
6084
6190
 
6085
- var Document = function(text) {
6086
- this.$lines = [];
6087
- if (text.length === 0) {
6191
+ var Document = function(textOrLines) {
6192
+ this.$lines = [""];
6193
+ if (textOrLines.length === 0) {
6088
6194
  this.$lines = [""];
6089
- } else if (Array.isArray(text)) {
6090
- this._insertLines(0, text);
6195
+ } else if (Array.isArray(textOrLines)) {
6196
+ this.insertMergedLines({row: 0, column: 0}, textOrLines);
6091
6197
  } else {
6092
- this.insert({row: 0, column:0}, text);
6198
+ this.insert({row: 0, column:0}, textOrLines);
6093
6199
  }
6094
6200
  };
6095
6201
 
@@ -6097,9 +6203,9 @@ var Document = function(text) {
6097
6203
 
6098
6204
  oop.implement(this, EventEmitter);
6099
6205
  this.setValue = function(text) {
6100
- var len = this.getLength();
6101
- this.remove(new Range(0, 0, len, this.getLine(len-1).length));
6102
- this.insert({row: 0, column:0}, text);
6206
+ var len = this.getLength() - 1;
6207
+ this.remove(new Range(0, 0, len, this.getLine(len).length));
6208
+ this.insert({row: 0, column: 0}, text);
6103
6209
  };
6104
6210
  this.getValue = function() {
6105
6211
  return this.getAllLines().join(this.getNewLineCharacter());
@@ -6107,14 +6213,15 @@ var Document = function(text) {
6107
6213
  this.createAnchor = function(row, column) {
6108
6214
  return new Anchor(this, row, column);
6109
6215
  };
6110
- if ("aaa".split(/a/).length === 0)
6216
+ if ("aaa".split(/a/).length === 0) {
6111
6217
  this.$split = function(text) {
6112
6218
  return text.replace(/\r\n|\r/g, "\n").split("\n");
6113
6219
  };
6114
- else
6220
+ } else {
6115
6221
  this.$split = function(text) {
6116
6222
  return text.split(/\r\n|\r|\n/);
6117
6223
  };
6224
+ }
6118
6225
 
6119
6226
 
6120
6227
  this.$detectNewLine = function(text) {
@@ -6161,251 +6268,246 @@ var Document = function(text) {
6161
6268
  return this.$lines.length;
6162
6269
  };
6163
6270
  this.getTextRange = function(range) {
6164
- if (range.start.row == range.end.row) {
6165
- return this.getLine(range.start.row)
6166
- .substring(range.start.column, range.end.column);
6271
+ return this.getLinesForRange(range).join(this.getNewLineCharacter());
6272
+ };
6273
+ this.getLinesForRange = function(range) {
6274
+ var lines;
6275
+ if (range.start.row === range.end.row) {
6276
+ lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];
6277
+ } else {
6278
+ lines = this.getLines(range.start.row, range.end.row);
6279
+ lines[0] = (lines[0] || "").substring(range.start.column);
6280
+ var l = lines.length - 1;
6281
+ if (range.end.row - range.start.row == l)
6282
+ lines[l] = lines[l].substring(0, range.end.column);
6167
6283
  }
6168
- var lines = this.getLines(range.start.row, range.end.row);
6169
- lines[0] = (lines[0] || "").substring(range.start.column);
6170
- var l = lines.length - 1;
6171
- if (range.end.row - range.start.row == l)
6172
- lines[l] = lines[l].substring(0, range.end.column);
6173
- return lines.join(this.getNewLineCharacter());
6284
+ return lines;
6174
6285
  };
6175
-
6176
- this.$clipPosition = function(position) {
6177
- var length = this.getLength();
6178
- if (position.row >= length) {
6179
- position.row = Math.max(0, length - 1);
6180
- position.column = this.getLine(length-1).length;
6181
- } else if (position.row < 0)
6182
- position.row = 0;
6183
- return position;
6286
+ this.insertLines = function(row, lines) {
6287
+ console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead.");
6288
+ return this.insertFullLines(row, lines);
6289
+ };
6290
+ this.removeLines = function(firstRow, lastRow) {
6291
+ console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead.");
6292
+ return this.removeFullLines(firstRow, lastRow);
6293
+ };
6294
+ this.insertNewLine = function(position) {
6295
+ console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.");
6296
+ return this.insertMergedLines(position, ["", ""]);
6184
6297
  };
6185
6298
  this.insert = function(position, text) {
6186
- if (!text || text.length === 0)
6187
- return position;
6188
-
6189
- position = this.$clipPosition(position);
6190
6299
  if (this.getLength() <= 1)
6191
6300
  this.$detectNewLine(text);
6192
-
6193
- var lines = this.$split(text);
6194
- var firstLine = lines.splice(0, 1)[0];
6195
- var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
6196
-
6197
- position = this.insertInLine(position, firstLine);
6198
- if (lastLine !== null) {
6199
- position = this.insertNewLine(position); // terminate first line
6200
- position = this._insertLines(position.row, lines);
6201
- position = this.insertInLine(position, lastLine || "");
6301
+
6302
+ return this.insertMergedLines(position, this.$split(text));
6303
+ };
6304
+ this.insertInLine = function(position, text) {
6305
+ var start = this.clippedPos(position.row, position.column);
6306
+ var end = this.pos(position.row, position.column + text.length);
6307
+
6308
+ this.applyDelta({
6309
+ start: start,
6310
+ end: end,
6311
+ action: "insert",
6312
+ lines: [text]
6313
+ }, true);
6314
+
6315
+ return this.clonePos(end);
6316
+ };
6317
+
6318
+ this.clippedPos = function(row, column) {
6319
+ var length = this.getLength();
6320
+ if (row === undefined) {
6321
+ row = length;
6322
+ } else if (row < 0) {
6323
+ row = 0;
6324
+ } else if (row >= length) {
6325
+ row = length - 1;
6326
+ column = undefined;
6202
6327
  }
6203
- return position;
6328
+ var line = this.getLine(row);
6329
+ if (column == undefined)
6330
+ column = line.length;
6331
+ column = Math.min(Math.max(column, 0), line.length);
6332
+ return {row: row, column: column};
6204
6333
  };
6205
- this.insertLines = function(row, lines) {
6206
- if (row >= this.getLength())
6207
- return this.insert({row: row, column: 0}, "\n" + lines.join("\n"));
6208
- return this._insertLines(Math.max(row, 0), lines);
6209
- };
6210
- this._insertLines = function(row, lines) {
6211
- if (lines.length == 0)
6212
- return {row: row, column: 0};
6213
- while (lines.length > 20000) {
6214
- var end = this._insertLines(row, lines.slice(0, 20000));
6215
- lines = lines.slice(20000);
6216
- row = end.row;
6217
- }
6218
-
6219
- var args = [row, 0];
6220
- args.push.apply(args, lines);
6221
- this.$lines.splice.apply(this.$lines, args);
6222
-
6223
- var range = new Range(row, 0, row + lines.length, 0);
6224
- var delta = {
6225
- action: "insertLines",
6226
- range: range,
6227
- lines: lines
6228
- };
6229
- this._signal("change", { data: delta });
6230
- return range.end;
6334
+
6335
+ this.clonePos = function(pos) {
6336
+ return {row: pos.row, column: pos.column};
6231
6337
  };
6232
- this.insertNewLine = function(position) {
6233
- position = this.$clipPosition(position);
6234
- var line = this.$lines[position.row] || "";
6235
-
6236
- this.$lines[position.row] = line.substring(0, position.column);
6237
- this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
6238
-
6239
- var end = {
6240
- row : position.row + 1,
6241
- column : 0
6242
- };
6243
-
6244
- var delta = {
6245
- action: "insertText",
6246
- range: Range.fromPoints(position, end),
6247
- text: this.getNewLineCharacter()
6248
- };
6249
- this._signal("change", { data: delta });
6250
-
6251
- return end;
6338
+
6339
+ this.pos = function(row, column) {
6340
+ return {row: row, column: column};
6252
6341
  };
6253
- this.insertInLine = function(position, text) {
6254
- if (text.length == 0)
6255
- return position;
6256
-
6257
- var line = this.$lines[position.row] || "";
6258
-
6259
- this.$lines[position.row] = line.substring(0, position.column) + text
6260
- + line.substring(position.column);
6261
-
6342
+
6343
+ this.$clipPosition = function(position) {
6344
+ var length = this.getLength();
6345
+ if (position.row >= length) {
6346
+ position.row = Math.max(0, length - 1);
6347
+ position.column = this.getLine(length - 1).length;
6348
+ } else {
6349
+ position.row = Math.max(0, position.row);
6350
+ position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);
6351
+ }
6352
+ return position;
6353
+ };
6354
+ this.insertFullLines = function(row, lines) {
6355
+ row = Math.min(Math.max(row, 0), this.getLength());
6356
+ var column = 0;
6357
+ if (row < this.getLength()) {
6358
+ lines = lines.concat([""]);
6359
+ column = 0;
6360
+ } else {
6361
+ lines = [""].concat(lines);
6362
+ row--;
6363
+ column = this.$lines[row].length;
6364
+ }
6365
+ this.insertMergedLines({row: row, column: column}, lines);
6366
+ };
6367
+ this.insertMergedLines = function(position, lines) {
6368
+ var start = this.clippedPos(position.row, position.column);
6262
6369
  var end = {
6263
- row : position.row,
6264
- column : position.column + text.length
6370
+ row: start.row + lines.length - 1,
6371
+ column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length
6265
6372
  };
6266
-
6267
- var delta = {
6268
- action: "insertText",
6269
- range: Range.fromPoints(position, end),
6270
- text: text
6271
- };
6272
- this._signal("change", { data: delta });
6273
-
6274
- return end;
6373
+
6374
+ this.applyDelta({
6375
+ start: start,
6376
+ end: end,
6377
+ action: "insert",
6378
+ lines: lines
6379
+ });
6380
+
6381
+ return this.clonePos(end);
6275
6382
  };
6276
6383
  this.remove = function(range) {
6277
- if (!(range instanceof Range))
6278
- range = Range.fromPoints(range.start, range.end);
6279
- range.start = this.$clipPosition(range.start);
6280
- range.end = this.$clipPosition(range.end);
6281
-
6282
- if (range.isEmpty())
6283
- return range.start;
6284
-
6285
- var firstRow = range.start.row;
6286
- var lastRow = range.end.row;
6287
-
6288
- if (range.isMultiLine()) {
6289
- var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
6290
- var lastFullRow = lastRow - 1;
6291
-
6292
- if (range.end.column > 0)
6293
- this.removeInLine(lastRow, 0, range.end.column);
6294
-
6295
- if (lastFullRow >= firstFullRow)
6296
- this._removeLines(firstFullRow, lastFullRow);
6297
-
6298
- if (firstFullRow != firstRow) {
6299
- this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
6300
- this.removeNewLine(range.start.row);
6301
- }
6302
- }
6303
- else {
6304
- this.removeInLine(firstRow, range.start.column, range.end.column);
6305
- }
6306
- return range.start;
6384
+ var start = this.clippedPos(range.start.row, range.start.column);
6385
+ var end = this.clippedPos(range.end.row, range.end.column);
6386
+ this.applyDelta({
6387
+ start: start,
6388
+ end: end,
6389
+ action: "remove",
6390
+ lines: this.getLinesForRange({start: start, end: end})
6391
+ });
6392
+ return this.clonePos(start);
6307
6393
  };
6308
6394
  this.removeInLine = function(row, startColumn, endColumn) {
6309
- if (startColumn == endColumn)
6310
- return;
6311
-
6312
- var range = new Range(row, startColumn, row, endColumn);
6313
- var line = this.getLine(row);
6314
- var removed = line.substring(startColumn, endColumn);
6315
- var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
6316
- this.$lines.splice(row, 1, newLine);
6317
-
6318
- var delta = {
6319
- action: "removeText",
6320
- range: range,
6321
- text: removed
6322
- };
6323
- this._signal("change", { data: delta });
6324
- return range.start;
6325
- };
6326
- this.removeLines = function(firstRow, lastRow) {
6327
- if (firstRow < 0 || lastRow >= this.getLength())
6328
- return this.remove(new Range(firstRow, 0, lastRow + 1, 0));
6329
- return this._removeLines(firstRow, lastRow);
6330
- };
6331
-
6332
- this._removeLines = function(firstRow, lastRow) {
6333
- var range = new Range(firstRow, 0, lastRow + 1, 0);
6334
- var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
6335
-
6336
- var delta = {
6337
- action: "removeLines",
6338
- range: range,
6339
- nl: this.getNewLineCharacter(),
6340
- lines: removed
6341
- };
6342
- this._signal("change", { data: delta });
6343
- return removed;
6395
+ var start = this.clippedPos(row, startColumn);
6396
+ var end = this.clippedPos(row, endColumn);
6397
+
6398
+ this.applyDelta({
6399
+ start: start,
6400
+ end: end,
6401
+ action: "remove",
6402
+ lines: this.getLinesForRange({start: start, end: end})
6403
+ }, true);
6404
+
6405
+ return this.clonePos(start);
6406
+ };
6407
+ this.removeFullLines = function(firstRow, lastRow) {
6408
+ firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);
6409
+ lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1);
6410
+ var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0;
6411
+ var deleteLastNewLine = lastRow < this.getLength() - 1;
6412
+ var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow );
6413
+ var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 );
6414
+ var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow );
6415
+ var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length );
6416
+ var range = new Range(startRow, startCol, endRow, endCol);
6417
+ var deletedLines = this.$lines.slice(firstRow, lastRow + 1);
6418
+
6419
+ this.applyDelta({
6420
+ start: range.start,
6421
+ end: range.end,
6422
+ action: "remove",
6423
+ lines: this.getLinesForRange(range)
6424
+ });
6425
+ return deletedLines;
6344
6426
  };
6345
6427
  this.removeNewLine = function(row) {
6346
- var firstLine = this.getLine(row);
6347
- var secondLine = this.getLine(row+1);
6348
-
6349
- var range = new Range(row, firstLine.length, row+1, 0);
6350
- var line = firstLine + secondLine;
6351
-
6352
- this.$lines.splice(row, 2, line);
6353
-
6354
- var delta = {
6355
- action: "removeText",
6356
- range: range,
6357
- text: this.getNewLineCharacter()
6358
- };
6359
- this._signal("change", { data: delta });
6428
+ if (row < this.getLength() - 1 && row >= 0) {
6429
+ this.applyDelta({
6430
+ start: this.pos(row, this.getLine(row).length),
6431
+ end: this.pos(row + 1, 0),
6432
+ action: "remove",
6433
+ lines: ["", ""]
6434
+ });
6435
+ }
6360
6436
  };
6361
6437
  this.replace = function(range, text) {
6362
- if (!(range instanceof Range))
6438
+ if (!range instanceof Range)
6363
6439
  range = Range.fromPoints(range.start, range.end);
6364
- if (text.length == 0 && range.isEmpty())
6440
+ if (text.length === 0 && range.isEmpty())
6365
6441
  return range.start;
6366
6442
  if (text == this.getTextRange(range))
6367
6443
  return range.end;
6368
6444
 
6369
6445
  this.remove(range);
6446
+ var end;
6370
6447
  if (text) {
6371
- var end = this.insert(range.start, text);
6448
+ end = this.insert(range.start, text);
6372
6449
  }
6373
6450
  else {
6374
6451
  end = range.start;
6375
6452
  }
6376
-
6453
+
6377
6454
  return end;
6378
6455
  };
6379
6456
  this.applyDeltas = function(deltas) {
6380
6457
  for (var i=0; i<deltas.length; i++) {
6381
- var delta = deltas[i];
6382
- var range = Range.fromPoints(delta.range.start, delta.range.end);
6383
-
6384
- if (delta.action == "insertLines")
6385
- this.insertLines(range.start.row, delta.lines);
6386
- else if (delta.action == "insertText")
6387
- this.insert(range.start, delta.text);
6388
- else if (delta.action == "removeLines")
6389
- this._removeLines(range.start.row, range.end.row - 1);
6390
- else if (delta.action == "removeText")
6391
- this.remove(range);
6458
+ this.applyDelta(deltas[i]);
6392
6459
  }
6393
6460
  };
6394
6461
  this.revertDeltas = function(deltas) {
6395
6462
  for (var i=deltas.length-1; i>=0; i--) {
6396
- var delta = deltas[i];
6397
-
6398
- var range = Range.fromPoints(delta.range.start, delta.range.end);
6399
-
6400
- if (delta.action == "insertLines")
6401
- this._removeLines(range.start.row, range.end.row - 1);
6402
- else if (delta.action == "insertText")
6403
- this.remove(range);
6404
- else if (delta.action == "removeLines")
6405
- this._insertLines(range.start.row, delta.lines);
6406
- else if (delta.action == "removeText")
6407
- this.insert(range.start, delta.text);
6463
+ this.revertDelta(deltas[i]);
6464
+ }
6465
+ };
6466
+ this.applyDelta = function(delta, doNotValidate) {
6467
+ var isInsert = delta.action == "insert";
6468
+ if (isInsert ? delta.lines.length <= 1 && !delta.lines[0]
6469
+ : !Range.comparePoints(delta.start, delta.end)) {
6470
+ return;
6408
6471
  }
6472
+
6473
+ if (isInsert && delta.lines.length > 20000)
6474
+ this.$splitAndapplyLargeDelta(delta, 20000);
6475
+ applyDelta(this.$lines, delta, doNotValidate);
6476
+ this._signal("change", delta);
6477
+ };
6478
+
6479
+ this.$splitAndapplyLargeDelta = function(delta, MAX) {
6480
+ var lines = delta.lines;
6481
+ var l = lines.length;
6482
+ var row = delta.start.row;
6483
+ var column = delta.start.column;
6484
+ var from = 0, to = 0;
6485
+ do {
6486
+ from = to;
6487
+ to += MAX - 1;
6488
+ var chunk = lines.slice(from, to);
6489
+ if (to > l) {
6490
+ delta.lines = chunk;
6491
+ delta.start.row = row + from;
6492
+ delta.start.column = column;
6493
+ break;
6494
+ }
6495
+ chunk.push("");
6496
+ this.applyDelta({
6497
+ start: this.pos(row + from, column),
6498
+ end: this.pos(row + to, column = 0),
6499
+ action: delta.action,
6500
+ lines: chunk
6501
+ }, true);
6502
+ } while(true);
6503
+ };
6504
+ this.revertDelta = function(delta) {
6505
+ this.applyDelta({
6506
+ start: this.clonePos(delta.start),
6507
+ end: this.clonePos(delta.end),
6508
+ action: (delta.action == "insert" ? "remove" : "insert"),
6509
+ lines: delta.lines.slice()
6510
+ });
6409
6511
  };
6410
6512
  this.indexToPosition = function(index, startRow) {
6411
6513
  var lines = this.$lines || this.getAllLines();
@@ -6456,11 +6558,10 @@ var BackgroundTokenizer = function(tokenizer, editor) {
6456
6558
  var endLine = -1;
6457
6559
  var doc = self.doc;
6458
6560
 
6561
+ var startLine = currentLine;
6459
6562
  while (self.lines[currentLine])
6460
6563
  currentLine++;
6461
-
6462
- var startLine = currentLine;
6463
-
6564
+
6464
6565
  var len = doc.getLength();
6465
6566
  var processedLines = 0;
6466
6567
  self.running = false;
@@ -6522,13 +6623,12 @@ var BackgroundTokenizer = function(tokenizer, editor) {
6522
6623
  }
6523
6624
 
6524
6625
  this.$updateOnChange = function(delta) {
6525
- var range = delta.range;
6526
- var startRow = range.start.row;
6527
- var len = range.end.row - startRow;
6626
+ var startRow = delta.start.row;
6627
+ var len = delta.end.row - startRow;
6528
6628
 
6529
6629
  if (len === 0) {
6530
6630
  this.lines[startRow] = null;
6531
- } else if (delta.action == "removeText" || delta.action == "removeLines") {
6631
+ } else if (delta.action == "remove") {
6532
6632
  this.lines.splice(startRow, len + 1, null);
6533
6633
  this.states.splice(startRow, len + 1, null);
6534
6634
  } else {
@@ -7000,14 +7100,13 @@ var RangeList = function() {
7000
7100
  this.session = null;
7001
7101
  };
7002
7102
 
7003
- this.$onChange = function(e) {
7004
- var changeRange = e.data.range;
7005
- if (e.data.action[0] == "i"){
7006
- var start = changeRange.start;
7007
- var end = changeRange.end;
7103
+ this.$onChange = function(delta) {
7104
+ if (delta.action == "insert"){
7105
+ var start = delta.start;
7106
+ var end = delta.end;
7008
7107
  } else {
7009
- var end = changeRange.start;
7010
- var start = changeRange.end;
7108
+ var end = delta.start;
7109
+ var start = delta.end;
7011
7110
  }
7012
7111
  var startRow = start.row;
7013
7112
  var endRow = end.row;
@@ -7870,15 +7969,13 @@ function Folding() {
7870
7969
  }
7871
7970
  };
7872
7971
 
7873
- this.updateFoldWidgets = function(e) {
7874
- var delta = e.data;
7875
- var range = delta.range;
7876
- var firstRow = range.start.row;
7877
- var len = range.end.row - firstRow;
7972
+ this.updateFoldWidgets = function(delta) {
7973
+ var firstRow = delta.start.row;
7974
+ var len = delta.end.row - firstRow;
7878
7975
 
7879
7976
  if (len === 0) {
7880
7977
  this.foldWidgets[firstRow] = null;
7881
- } else if (delta.action == "removeText" || delta.action == "removeLines") {
7978
+ } else if (delta.action == 'remove') {
7882
7979
  this.foldWidgets.splice(firstRow, len + 1, null);
7883
7980
  } else {
7884
7981
  var args = Array(len + 1);
@@ -7988,7 +8085,7 @@ function BracketMatch() {
7988
8085
  typeRe = new RegExp(
7989
8086
  "(\\.?" +
7990
8087
  token.type.replace(".", "\\.").replace("rparen", ".paren")
7991
- .replace(/\b(?:end|start|begin)\b/, "")
8088
+ .replace(/\b(?:end)\b/, "(?:start|begin|end)")
7992
8089
  + ")+"
7993
8090
  );
7994
8091
  }
@@ -8040,7 +8137,7 @@ function BracketMatch() {
8040
8137
  typeRe = new RegExp(
8041
8138
  "(\\.?" +
8042
8139
  token.type.replace(".", "\\.").replace("lparen", ".paren")
8043
- .replace(/\b(?:end|start|begin)\b/, "")
8140
+ .replace(/\b(?:start|begin)\b/, "(?:start|begin|end)")
8044
8141
  + ")+"
8045
8142
  );
8046
8143
  }
@@ -8106,7 +8203,7 @@ var EditSession = function(text, mode) {
8106
8203
  this.$foldData = [];
8107
8204
  this.$foldData.toString = function() {
8108
8205
  return this.join("\n");
8109
- }
8206
+ };
8110
8207
  this.on("changeFold", this.onChangeFold.bind(this));
8111
8208
  this.$onChange = this.onChange.bind(this);
8112
8209
 
@@ -8187,13 +8284,12 @@ var EditSession = function(text, mode) {
8187
8284
  this.$resetRowCache(fold.start.row);
8188
8285
  };
8189
8286
 
8190
- this.onChange = function(e) {
8191
- var delta = e.data;
8287
+ this.onChange = function(delta) {
8192
8288
  this.$modified = true;
8193
8289
 
8194
- this.$resetRowCache(delta.range.start.row);
8290
+ this.$resetRowCache(delta.start.row);
8195
8291
 
8196
- var removedFolds = this.$updateInternalDataOnChange(e);
8292
+ var removedFolds = this.$updateInternalDataOnChange(delta);
8197
8293
  if (!this.$fromUndo && this.$undoManager && !delta.ignore) {
8198
8294
  this.$deltasDoc.push(delta);
8199
8295
  if (removedFolds && removedFolds.length != 0) {
@@ -8207,7 +8303,7 @@ var EditSession = function(text, mode) {
8207
8303
  }
8208
8304
 
8209
8305
  this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta);
8210
- this._signal("change", e);
8306
+ this._signal("change", delta);
8211
8307
  };
8212
8308
  this.setValue = function(text) {
8213
8309
  this.doc.setValue(text);
@@ -8723,6 +8819,9 @@ var EditSession = function(text, mode) {
8723
8819
  this.remove = function(range) {
8724
8820
  return this.doc.remove(range);
8725
8821
  };
8822
+ this.removeFullLines = function(firstRow, lastRow){
8823
+ return this.doc.removeFullLines(firstRow, lastRow);
8824
+ };
8726
8825
  this.undoChanges = function(deltas, dontSelect) {
8727
8826
  if (!deltas.length)
8728
8827
  return;
@@ -8775,39 +8874,36 @@ var EditSession = function(text, mode) {
8775
8874
 
8776
8875
  this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
8777
8876
  function isInsert(delta) {
8778
- var insert =
8779
- delta.action === "insertText" || delta.action === "insertLines";
8780
- return isUndo ? !insert : insert;
8877
+ return isUndo ? delta.action !== "insert" : delta.action === "insert";
8781
8878
  }
8782
8879
 
8783
8880
  var delta = deltas[0];
8784
8881
  var range, point;
8785
8882
  var lastDeltaIsInsert = false;
8786
8883
  if (isInsert(delta)) {
8787
- range = Range.fromPoints(delta.range.start, delta.range.end);
8884
+ range = Range.fromPoints(delta.start, delta.end);
8788
8885
  lastDeltaIsInsert = true;
8789
8886
  } else {
8790
- range = Range.fromPoints(delta.range.start, delta.range.start);
8887
+ range = Range.fromPoints(delta.start, delta.start);
8791
8888
  lastDeltaIsInsert = false;
8792
8889
  }
8793
8890
 
8794
8891
  for (var i = 1; i < deltas.length; i++) {
8795
8892
  delta = deltas[i];
8796
8893
  if (isInsert(delta)) {
8797
- point = delta.range.start;
8894
+ point = delta.start;
8798
8895
  if (range.compare(point.row, point.column) == -1) {
8799
- range.setStart(delta.range.start);
8896
+ range.setStart(point);
8800
8897
  }
8801
- point = delta.range.end;
8898
+ point = delta.end;
8802
8899
  if (range.compare(point.row, point.column) == 1) {
8803
- range.setEnd(delta.range.end);
8900
+ range.setEnd(point);
8804
8901
  }
8805
8902
  lastDeltaIsInsert = true;
8806
8903
  } else {
8807
- point = delta.range.start;
8904
+ point = delta.start;
8808
8905
  if (range.compare(point.row, point.column) == -1) {
8809
- range =
8810
- Range.fromPoints(delta.range.start, delta.range.start);
8906
+ range = Range.fromPoints(delta.start, delta.start);
8811
8907
  }
8812
8908
  lastDeltaIsInsert = false;
8813
8909
  }
@@ -8875,7 +8971,7 @@ var EditSession = function(text, mode) {
8875
8971
  this.indentRows = function(startRow, endRow, indentString) {
8876
8972
  indentString = indentString.replace(/\t/g, this.getTabString());
8877
8973
  for (var row=startRow; row<=endRow; row++)
8878
- this.insert({row: row, column:0}, indentString);
8974
+ this.doc.insertInLine({row: row, column: 0}, indentString);
8879
8975
  };
8880
8976
  this.outdentRows = function (range) {
8881
8977
  var rowRange = range.collapseRows();
@@ -8925,11 +9021,11 @@ var EditSession = function(text, mode) {
8925
9021
  x.end.row += diff;
8926
9022
  return x;
8927
9023
  });
8928
-
9024
+
8929
9025
  var lines = dir == 0
8930
9026
  ? this.doc.getLines(firstRow, lastRow)
8931
- : this.doc.removeLines(firstRow, lastRow);
8932
- this.doc.insertLines(firstRow+diff, lines);
9027
+ : this.doc.removeFullLines(firstRow, lastRow);
9028
+ this.doc.insertFullLines(firstRow+diff, lines);
8933
9029
  folds.length && this.addFolds(folds);
8934
9030
  return diff;
8935
9031
  };
@@ -9071,34 +9167,23 @@ var EditSession = function(text, mode) {
9071
9167
  };
9072
9168
  };
9073
9169
 
9074
- this.$updateInternalDataOnChange = function(e) {
9170
+ this.$updateInternalDataOnChange = function(delta) {
9075
9171
  var useWrapMode = this.$useWrapMode;
9076
- var len;
9077
- var action = e.data.action;
9078
- var firstRow = e.data.range.start.row;
9079
- var lastRow = e.data.range.end.row;
9080
- var start = e.data.range.start;
9081
- var end = e.data.range.end;
9172
+ var action = delta.action;
9173
+ var start = delta.start;
9174
+ var end = delta.end;
9175
+ var firstRow = start.row;
9176
+ var lastRow = end.row;
9177
+ var len = lastRow - firstRow;
9082
9178
  var removedFolds = null;
9083
-
9084
- if (action.indexOf("Lines") != -1) {
9085
- if (action == "insertLines") {
9086
- lastRow = firstRow + (e.data.lines.length);
9087
- } else {
9088
- lastRow = firstRow;
9089
- }
9090
- len = e.data.lines ? e.data.lines.length : lastRow - firstRow;
9091
- } else {
9092
- len = lastRow - firstRow;
9093
- }
9094
-
9179
+
9095
9180
  this.$updating = true;
9096
9181
  if (len != 0) {
9097
- if (action.indexOf("remove") != -1) {
9182
+ if (action === "remove") {
9098
9183
  this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len);
9099
9184
 
9100
9185
  var foldLines = this.$foldData;
9101
- removedFolds = this.getFoldsInRange(e.data.range);
9186
+ removedFolds = this.getFoldsInRange(delta);
9102
9187
  this.removeFolds(removedFolds);
9103
9188
 
9104
9189
  var foldLine = this.getFoldLine(end.row);
@@ -9155,9 +9240,9 @@ var EditSession = function(text, mode) {
9155
9240
  }
9156
9241
  }
9157
9242
  } else {
9158
- len = Math.abs(e.data.range.start.column - e.data.range.end.column);
9159
- if (action.indexOf("remove") != -1) {
9160
- removedFolds = this.getFoldsInRange(e.data.range);
9243
+ len = Math.abs(delta.start.column - delta.end.column);
9244
+ if (action === "remove") {
9245
+ removedFolds = this.getFoldsInRange(delta);
9161
9246
  this.removeFolds(removedFolds);
9162
9247
 
9163
9248
  len = -len;
@@ -9239,7 +9324,7 @@ var EditSession = function(text, mode) {
9239
9324
  TAB_SPACE = 12;
9240
9325
 
9241
9326
 
9242
- this.$computeWrapSplits = function(tokens, wrapLimit) {
9327
+ this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) {
9243
9328
  if (tokens.length == 0) {
9244
9329
  return [];
9245
9330
  }
@@ -9250,6 +9335,31 @@ var EditSession = function(text, mode) {
9250
9335
 
9251
9336
  var isCode = this.$wrapAsCode;
9252
9337
 
9338
+ var indentedSoftWrap = this.$indentedSoftWrap;
9339
+ var maxIndent = wrapLimit <= Math.max(2 * tabSize, 8)
9340
+ || indentedSoftWrap === false ? 0 : Math.floor(wrapLimit / 2);
9341
+
9342
+ function getWrapIndent() {
9343
+ var indentation = 0;
9344
+ if (maxIndent === 0)
9345
+ return indentation;
9346
+ if (indentedSoftWrap) {
9347
+ for (var i = 0; i < tokens.length; i++) {
9348
+ var token = tokens[i];
9349
+ if (token == SPACE)
9350
+ indentation += 1;
9351
+ else if (token == TAB)
9352
+ indentation += tabSize;
9353
+ else if (token == TAB_SPACE)
9354
+ continue;
9355
+ else
9356
+ break;
9357
+ }
9358
+ }
9359
+ if (isCode && indentedSoftWrap !== false)
9360
+ indentation += tabSize;
9361
+ return Math.min(indentation, maxIndent);
9362
+ }
9253
9363
  function addSplit(screenPos) {
9254
9364
  var displayed = tokens.slice(lastSplit, screenPos);
9255
9365
  var len = displayed.length;
@@ -9261,13 +9371,17 @@ var EditSession = function(text, mode) {
9261
9371
  len -= 1;
9262
9372
  });
9263
9373
 
9374
+ if (!splits.length) {
9375
+ indent = getWrapIndent();
9376
+ splits.indent = indent;
9377
+ }
9264
9378
  lastDocSplit += len;
9265
9379
  splits.push(lastDocSplit);
9266
9380
  lastSplit = screenPos;
9267
9381
  }
9268
-
9269
- while (displayLength - lastSplit > wrapLimit) {
9270
- var split = lastSplit + wrapLimit;
9382
+ var indent = 0;
9383
+ while (displayLength - lastSplit > wrapLimit - indent) {
9384
+ var split = lastSplit + wrapLimit - indent;
9271
9385
  if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) {
9272
9386
  addSplit(split);
9273
9387
  continue;
@@ -9294,7 +9408,7 @@ var EditSession = function(text, mode) {
9294
9408
  addSplit(split);
9295
9409
  continue;
9296
9410
  }
9297
- var minSplit = Math.max(split - (isCode ? 10 : wrapLimit-(wrapLimit>>2)), lastSplit - 1);
9411
+ var minSplit = Math.max(split - (wrapLimit -(wrapLimit>>2)), lastSplit - 1);
9298
9412
  while (split > minSplit && tokens[split] < PLACEHOLDER_START) {
9299
9413
  split --;
9300
9414
  }
@@ -9317,7 +9431,7 @@ var EditSession = function(text, mode) {
9317
9431
  split = lastSplit + wrapLimit;
9318
9432
  if (tokens[split] == CHAR_EXT)
9319
9433
  split--;
9320
- addSplit(split);
9434
+ addSplit(split - indent);
9321
9435
  }
9322
9436
  return splits;
9323
9437
  };
@@ -9393,6 +9507,16 @@ var EditSession = function(text, mode) {
9393
9507
  return this.$wrapData[row].length + 1;
9394
9508
  }
9395
9509
  };
9510
+
9511
+ this.getRowWrapIndent = function(screenRow) {
9512
+ if (this.$useWrapMode) {
9513
+ var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
9514
+ var splits = this.$wrapData[pos.row];
9515
+ return splits.length && splits[0] < pos.column ? splits.indent : 0;
9516
+ } else {
9517
+ return 0;
9518
+ }
9519
+ }
9396
9520
  this.getScreenLastRowColumn = function(screenRow) {
9397
9521
  var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE);
9398
9522
  return this.documentToScreenColumn(pos.row, pos.column);
@@ -9483,20 +9607,21 @@ var EditSession = function(text, mode) {
9483
9607
  line = this.getLine(docRow);
9484
9608
  foldLine = null;
9485
9609
  }
9486
-
9610
+ var wrapIndent = 0;
9487
9611
  if (this.$useWrapMode) {
9488
9612
  var splits = this.$wrapData[docRow];
9489
9613
  if (splits) {
9490
9614
  var splitIndex = Math.floor(screenRow - row);
9491
9615
  column = splits[splitIndex];
9492
9616
  if(splitIndex > 0 && splits.length) {
9617
+ wrapIndent = splits.indent;
9493
9618
  docColumn = splits[splitIndex - 1] || splits[splits.length - 1];
9494
9619
  line = line.substring(docColumn);
9495
9620
  }
9496
9621
  }
9497
9622
  }
9498
9623
 
9499
- docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
9624
+ docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1];
9500
9625
  if (this.$useWrapMode && docColumn >= column)
9501
9626
  docColumn = column - 1;
9502
9627
 
@@ -9568,6 +9693,7 @@ var EditSession = function(text, mode) {
9568
9693
  textLine = this.getLine(docRow).substring(0, docColumn);
9569
9694
  foldStartRow = docRow;
9570
9695
  }
9696
+ var wrapIndent = 0;
9571
9697
  if (this.$useWrapMode) {
9572
9698
  var wrapRow = this.$wrapData[foldStartRow];
9573
9699
  if (wrapRow) {
@@ -9579,12 +9705,13 @@ var EditSession = function(text, mode) {
9579
9705
  textLine = textLine.substring(
9580
9706
  wrapRow[screenRowOffset - 1] || 0, textLine.length
9581
9707
  );
9708
+ wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0;
9582
9709
  }
9583
9710
  }
9584
9711
 
9585
9712
  return {
9586
9713
  row: screenRow,
9587
- column: this.$getStringScreenWidth(textLine)[0]
9714
+ column: wrapIndent + this.$getStringScreenWidth(textLine)[0]
9588
9715
  };
9589
9716
  };
9590
9717
  this.documentToScreenColumn = function(row, docColumn) {
@@ -9729,6 +9856,7 @@ config.defineOptions(EditSession.prototype, "session", {
9729
9856
  },
9730
9857
  initialValue: "auto"
9731
9858
  },
9859
+ indentedSoftWrap: { initialValue: true },
9732
9860
  firstLineNumber: {
9733
9861
  set: function() {this._signal("changeBreakpoint");},
9734
9862
  initialValue: 1
@@ -10134,9 +10262,12 @@ MultiHashHandler.prototype = HashHandler.prototype;
10134
10262
  }
10135
10263
  };
10136
10264
 
10137
- this.bindKey = function(key, command, asDefault) {
10138
- if (typeof key == "object")
10265
+ this.bindKey = function(key, command, position) {
10266
+ if (typeof key == "object") {
10267
+ if (position == undefined)
10268
+ position = key.position;
10139
10269
  key = key[this.platform];
10270
+ }
10140
10271
  if (!key)
10141
10272
  return;
10142
10273
  if (typeof command == "function")
@@ -10157,11 +10288,15 @@ MultiHashHandler.prototype = HashHandler.prototype;
10157
10288
  }
10158
10289
  var binding = this.parseKeys(keyPart);
10159
10290
  var id = KEY_MODS[binding.hashId] + binding.key;
10160
- this._addCommandToBinding(chain + id, command, asDefault);
10291
+ this._addCommandToBinding(chain + id, command, position);
10161
10292
  }, this);
10162
10293
  };
10163
10294
 
10164
- this._addCommandToBinding = function(keyId, command, asDefault) {
10295
+ function getPosition(command) {
10296
+ return typeof command == "object" && command.bindKey
10297
+ && command.bindKey.position || 0;
10298
+ }
10299
+ this._addCommandToBinding = function(keyId, command, position) {
10165
10300
  var ckb = this.commandKeyBinding, i;
10166
10301
  if (!command) {
10167
10302
  delete ckb[keyId];
@@ -10173,11 +10308,21 @@ MultiHashHandler.prototype = HashHandler.prototype;
10173
10308
  } else if ((i = ckb[keyId].indexOf(command)) != -1) {
10174
10309
  ckb[keyId].splice(i, 1);
10175
10310
  }
10176
-
10177
- if (asDefault || command.isDefault)
10178
- ckb[keyId].unshift(command);
10179
- else
10180
- ckb[keyId].push(command);
10311
+
10312
+ if (typeof position != "number") {
10313
+ if (position || command.isDefault)
10314
+ position = -100;
10315
+ else
10316
+ position = getPosition(command);
10317
+ }
10318
+ var commands = ckb[keyId];
10319
+ for (i = 0; i < commands.length; i++) {
10320
+ var other = commands[i];
10321
+ var otherPos = getPosition(other);
10322
+ if (otherPos > position)
10323
+ break;
10324
+ }
10325
+ commands.splice(i, 0, command);
10181
10326
  }
10182
10327
  };
10183
10328
 
@@ -10263,10 +10408,18 @@ MultiHashHandler.prototype = HashHandler.prototype;
10263
10408
  }
10264
10409
  }
10265
10410
 
10266
- if (data.$keyChain && keyCode > 0)
10267
- data.$keyChain = "";
10411
+ if (data.$keyChain) {
10412
+ if ((!hashId || hashId == 4) && keyString.length == 1)
10413
+ data.$keyChain = data.$keyChain.slice(0, -key.length - 1); // wait for input
10414
+ else if (hashId == -1 || keyCode > 0)
10415
+ data.$keyChain = ""; // reset keyChain
10416
+ }
10268
10417
  return {command: command};
10269
10418
  };
10419
+
10420
+ this.getStatusText = function(editor, data) {
10421
+ return data.$keyChain || "";
10422
+ };
10270
10423
 
10271
10424
  }).call(HashHandler.prototype);
10272
10425
 
@@ -10771,6 +10924,11 @@ exports.commands = [{
10771
10924
  exec: function() {},
10772
10925
  passEvent: true,
10773
10926
  readOnly: true
10927
+ }, {
10928
+ name: "copy",
10929
+ exec: function(editor) {
10930
+ },
10931
+ readOnly: true
10774
10932
  },
10775
10933
  {
10776
10934
  name: "cut",
@@ -10785,6 +10943,12 @@ exports.commands = [{
10785
10943
  },
10786
10944
  scrollIntoView: "cursor",
10787
10945
  multiSelectAction: "forEach"
10946
+ }, {
10947
+ name: "paste",
10948
+ exec: function(editor, args) {
10949
+ editor.$handlePaste(args);
10950
+ },
10951
+ scrollIntoView: "cursor"
10788
10952
  }, {
10789
10953
  name: "removeline",
10790
10954
  bindKey: bindKey("Ctrl-D", "Command-D"),
@@ -11164,7 +11328,7 @@ var Editor = function(renderer, session) {
11164
11328
  args: commadEvent.args,
11165
11329
  scrollTop: this.renderer.scrollTop
11166
11330
  };
11167
- if (this.curOp.command.name)
11331
+ if (this.curOp.command.name && this.curOp.command.scrollIntoView !== undefined)
11168
11332
  this.$blockScrolling++;
11169
11333
  };
11170
11334
 
@@ -11174,10 +11338,13 @@ var Editor = function(renderer, session) {
11174
11338
  return this.curOp = null;
11175
11339
  this._signal("beforeEndOperation");
11176
11340
  var command = this.curOp.command;
11177
- if (command.name && this.$blockScrolling)
11341
+ if (command.name && this.$blockScrolling > 0)
11178
11342
  this.$blockScrolling--;
11179
- if (command && command.scrollIntoView) {
11180
- switch (command.scrollIntoView) {
11343
+ var scrollIntoView = command && command.scrollIntoView;
11344
+ if (scrollIntoView) {
11345
+ switch (scrollIntoView) {
11346
+ case "center-animate":
11347
+ scrollIntoView = "animate";
11181
11348
  case "center":
11182
11349
  this.renderer.scrollCursorIntoView(null, 0.5);
11183
11350
  break;
@@ -11195,7 +11362,7 @@ var Editor = function(renderer, session) {
11195
11362
  default:
11196
11363
  break;
11197
11364
  }
11198
- if (command.scrollIntoView == "animate")
11365
+ if (scrollIntoView == "animate")
11199
11366
  this.renderer.animateScrolling(this.curOp.scrollTop);
11200
11367
  }
11201
11368
 
@@ -11259,6 +11426,8 @@ var Editor = function(renderer, session) {
11259
11426
  this.setSession = function(session) {
11260
11427
  if (this.session == session)
11261
11428
  return;
11429
+ if (this.curOp) this.endOperation();
11430
+ this.curOp = {};
11262
11431
 
11263
11432
  var oldSession = this.session;
11264
11433
  if (oldSession) {
@@ -11358,6 +11527,8 @@ var Editor = function(renderer, session) {
11358
11527
  oldSession: oldSession
11359
11528
  });
11360
11529
 
11530
+ this.curOp = null;
11531
+
11361
11532
  oldSession && oldSession._signal("changeEditor", {oldEditor: this});
11362
11533
  session && session._signal("changeEditor", {editor: this});
11363
11534
  };
@@ -11542,18 +11713,12 @@ var Editor = function(renderer, session) {
11542
11713
  this.$cursorChange = function() {
11543
11714
  this.renderer.updateCursor();
11544
11715
  };
11545
- this.onDocumentChange = function(e) {
11546
- var delta = e.data;
11547
- var range = delta.range;
11548
- var lastRow;
11716
+ this.onDocumentChange = function(delta) {
11717
+ var wrap = this.session.$useWrapMode;
11718
+ var lastRow = (delta.start.row == delta.end.row ? delta.end.row : Infinity);
11719
+ this.renderer.updateLines(delta.start.row, lastRow, wrap);
11549
11720
 
11550
- if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines")
11551
- lastRow = range.end.row;
11552
- else
11553
- lastRow = Infinity;
11554
- this.renderer.updateLines(range.start.row, lastRow, this.session.$useWrapMode);
11555
-
11556
- this._signal("change", e);
11721
+ this._signal("change", delta);
11557
11722
  this.$cursorChange();
11558
11723
  this.$updateHighlightActiveLine();
11559
11724
  };
@@ -11718,13 +11883,16 @@ var Editor = function(renderer, session) {
11718
11883
  this.onCut = function() {
11719
11884
  this.commands.exec("cut", this);
11720
11885
  };
11721
- this.onPaste = function(text) {
11722
- if (this.$readOnly)
11723
- return;
11724
-
11725
- var e = {text: text};
11886
+ this.onPaste = function(text, event) {
11887
+ var e = {text: text, event: event};
11888
+ this.commands.exec("paste", this, e);
11889
+ };
11890
+
11891
+ this.$handlePaste = function(e) {
11892
+ if (typeof e == "string")
11893
+ e = {text: e};
11726
11894
  this._signal("paste", e);
11727
- text = e.text;
11895
+ var text = e.text;
11728
11896
  if (!this.inMultiSelectMode || this.inVirtualSelectionMode) {
11729
11897
  this.insert(text);
11730
11898
  } else {
@@ -11742,7 +11910,6 @@ var Editor = function(renderer, session) {
11742
11910
  this.session.insert(range.start, lines[i]);
11743
11911
  }
11744
11912
  }
11745
- this.renderer.scrollCursorIntoView();
11746
11913
  };
11747
11914
 
11748
11915
  this.execCommand = function(command, args) {
@@ -12185,15 +12352,7 @@ var Editor = function(renderer, session) {
12185
12352
  };
12186
12353
  this.removeLines = function() {
12187
12354
  var rows = this.$getSelectedRows();
12188
- var range;
12189
- if (rows.first === 0 || rows.last+1 < this.session.getLength())
12190
- range = new Range(rows.first, 0, rows.last+1, 0);
12191
- else
12192
- range = new Range(
12193
- rows.first-1, this.session.getLine(rows.first-1).length,
12194
- rows.last, this.session.getLine(rows.last).length
12195
- );
12196
- this.session.remove(range);
12355
+ this.session.removeFullLines(rows.first, rows.last);
12197
12356
  this.clearSelection();
12198
12357
  };
12199
12358
 
@@ -12900,6 +13059,7 @@ config.defineOptions(Editor.prototype, "editor", {
12900
13059
  useSoftTabs: "session",
12901
13060
  tabSize: "session",
12902
13061
  wrap: "session",
13062
+ indentedSoftWrap: "session",
12903
13063
  foldStyle: "session",
12904
13064
  mode: "session"
12905
13065
  });
@@ -12915,42 +13075,39 @@ var UndoManager = function() {
12915
13075
 
12916
13076
  (function() {
12917
13077
  this.execute = function(options) {
12918
- var deltas = options.args[0];
13078
+ var deltaSets = options.args[0];
12919
13079
  this.$doc = options.args[1];
12920
13080
  if (options.merge && this.hasUndo()){
12921
13081
  this.dirtyCounter--;
12922
- deltas = this.$undoStack.pop().concat(deltas);
13082
+ deltaSets = this.$undoStack.pop().concat(deltaSets);
12923
13083
  }
12924
- this.$undoStack.push(deltas);
13084
+ this.$undoStack.push(deltaSets);
12925
13085
  this.$redoStack = [];
12926
-
12927
13086
  if (this.dirtyCounter < 0) {
12928
13087
  this.dirtyCounter = NaN;
12929
13088
  }
12930
13089
  this.dirtyCounter++;
12931
13090
  };
12932
13091
  this.undo = function(dontSelect) {
12933
- var deltas = this.$undoStack.pop();
13092
+ var deltaSets = this.$undoStack.pop();
12934
13093
  var undoSelectionRange = null;
12935
- if (deltas) {
12936
- undoSelectionRange =
12937
- this.$doc.undoChanges(deltas, dontSelect);
12938
- this.$redoStack.push(deltas);
13094
+ if (deltaSets) {
13095
+ undoSelectionRange = this.$doc.undoChanges(this.$deserializeDeltas(deltaSets), dontSelect);
13096
+ this.$redoStack.push(deltaSets);
12939
13097
  this.dirtyCounter--;
12940
13098
  }
12941
13099
 
12942
13100
  return undoSelectionRange;
12943
13101
  };
12944
13102
  this.redo = function(dontSelect) {
12945
- var deltas = this.$redoStack.pop();
13103
+ var deltaSets = this.$redoStack.pop();
12946
13104
  var redoSelectionRange = null;
12947
- if (deltas) {
13105
+ if (deltaSets) {
12948
13106
  redoSelectionRange =
12949
- this.$doc.redoChanges(deltas, dontSelect);
12950
- this.$undoStack.push(deltas);
13107
+ this.$doc.redoChanges(this.$deserializeDeltas(deltaSets), dontSelect);
13108
+ this.$undoStack.push(deltaSets);
12951
13109
  this.dirtyCounter++;
12952
13110
  }
12953
-
12954
13111
  return redoSelectionRange;
12955
13112
  };
12956
13113
  this.reset = function() {
@@ -12970,7 +13127,48 @@ var UndoManager = function() {
12970
13127
  this.isClean = function() {
12971
13128
  return this.dirtyCounter === 0;
12972
13129
  };
12973
-
13130
+ this.$serializeDeltas = function(deltaSets) {
13131
+ return cloneDeltaSetsObj(deltaSets, $serializeDelta);
13132
+ };
13133
+ this.$deserializeDeltas = function(deltaSets) {
13134
+ return cloneDeltaSetsObj(deltaSets, $deserializeDelta);
13135
+ };
13136
+
13137
+ function $serializeDelta(delta){
13138
+ return {
13139
+ action: delta.action,
13140
+ start: delta.start,
13141
+ end: delta.end,
13142
+ lines: delta.lines.length == 1 ? null : delta.lines,
13143
+ text: delta.lines.length == 1 ? delta.lines[0] : null,
13144
+ };
13145
+ }
13146
+
13147
+ function $deserializeDelta(delta) {
13148
+ return {
13149
+ action: delta.action,
13150
+ start: delta.start,
13151
+ end: delta.end,
13152
+ lines: delta.lines || [delta.text]
13153
+ };
13154
+ }
13155
+
13156
+ function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) {
13157
+ var deltaSets_new = new Array(deltaSets_old.length);
13158
+ for (var i = 0; i < deltaSets_old.length; i++) {
13159
+ var deltaSet_old = deltaSets_old[i];
13160
+ var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)};
13161
+
13162
+ for (var j = 0; j < deltaSet_old.deltas.length; j++) {
13163
+ var delta_old = deltaSet_old.deltas[j];
13164
+ deltaSet_new.deltas[j] = fnGetModifiedDelta(delta_old);
13165
+ }
13166
+
13167
+ deltaSets_new[i] = deltaSet_new;
13168
+ }
13169
+ return deltaSets_new;
13170
+ }
13171
+
12974
13172
  }).call(UndoManager.prototype);
12975
13173
 
12976
13174
  exports.UndoManager = UndoManager;
@@ -13047,15 +13245,13 @@ var Gutter = function(parentEl) {
13047
13245
  }
13048
13246
  };
13049
13247
 
13050
- this.$updateAnnotations = function (e) {
13248
+ this.$updateAnnotations = function (delta) {
13051
13249
  if (!this.$annotations.length)
13052
13250
  return;
13053
- var delta = e.data;
13054
- var range = delta.range;
13055
- var firstRow = range.start.row;
13056
- var len = range.end.row - firstRow;
13251
+ var firstRow = delta.start.row;
13252
+ var len = delta.end.row - firstRow;
13057
13253
  if (len === 0) {
13058
- } else if (delta.action == "removeText" || delta.action == "removeLines") {
13254
+ } else if (delta.action == 'remove') {
13059
13255
  this.$annotations.splice(firstRow, len + 1, null);
13060
13256
  } else {
13061
13257
  var args = new Array(len + 1);
@@ -13293,7 +13489,7 @@ var Marker = function(parentEl) {
13293
13489
  else
13294
13490
  this.drawMultiLineMarker(html, range, marker.clazz, config);
13295
13491
  } else {
13296
- this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config);
13492
+ this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config);
13297
13493
  }
13298
13494
  }
13299
13495
  this.element.innerHTML = html.join("");
@@ -13302,23 +13498,30 @@ var Marker = function(parentEl) {
13302
13498
  this.$getTop = function(row, layerConfig) {
13303
13499
  return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
13304
13500
  };
13305
- this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {
13306
- var row = range.start.row;
13307
13501
 
13308
- var lineRange = new Range(
13309
- row, range.start.column,
13310
- row, this.session.getScreenLastRowColumn(row)
13311
- );
13312
- this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " ace_start", layerConfig, 1, extraStyle);
13313
- row = range.end.row;
13314
- lineRange = new Range(row, 0, row, range.end.column);
13315
- this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle);
13316
-
13317
- for (row = range.start.row + 1; row < range.end.row; row++) {
13318
- lineRange.start.row = row;
13319
- lineRange.end.row = row;
13320
- lineRange.end.column = this.session.getScreenLastRowColumn(row);
13321
- this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle);
13502
+ function getBorderClass(tl, tr, br, bl) {
13503
+ return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0);
13504
+ }
13505
+ this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {
13506
+ var session = this.session;
13507
+ var start = range.start.row;
13508
+ var end = range.end.row;
13509
+ var row = start;
13510
+ var prev = 0;
13511
+ var curr = 0;
13512
+ var next = session.getScreenLastRowColumn(row);
13513
+ var lineRange = new Range(row, range.start.column, row, curr);
13514
+ for (; row <= end; row++) {
13515
+ lineRange.start.row = lineRange.end.row = row;
13516
+ lineRange.start.column = row == start ? range.start.column : session.getRowWrapIndent(row);
13517
+ lineRange.end.column = next;
13518
+ prev = curr;
13519
+ curr = next;
13520
+ next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column;
13521
+ this.drawSingleLineMarker(stringBuilder, lineRange,
13522
+ clazz + (row == start ? " ace_start" : "") + " ace_br"
13523
+ + getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end),
13524
+ layerConfig, row == end ? 0 : 1, extraStyle);
13322
13525
  }
13323
13526
  };
13324
13527
  this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) {
@@ -13329,7 +13532,7 @@ var Marker = function(parentEl) {
13329
13532
  extraStyle = extraStyle || "";
13330
13533
 
13331
13534
  stringBuilder.push(
13332
- "<div class='", clazz, " ace_start' style='",
13535
+ "<div class='", clazz, " ace_br1 ace_start' style='",
13333
13536
  "height:", height, "px;",
13334
13537
  "right:0;",
13335
13538
  "top:", top, "px;",
@@ -13339,19 +13542,21 @@ var Marker = function(parentEl) {
13339
13542
  var width = range.end.column * config.characterWidth;
13340
13543
 
13341
13544
  stringBuilder.push(
13342
- "<div class='", clazz, "' style='",
13545
+ "<div class='", clazz, " ace_br12' style='",
13343
13546
  "height:", height, "px;",
13344
13547
  "width:", width, "px;",
13345
13548
  "top:", top, "px;",
13346
13549
  "left:", padding, "px;", extraStyle, "'></div>"
13347
13550
  );
13348
13551
  height = (range.end.row - range.start.row - 1) * config.lineHeight;
13349
- if (height < 0)
13552
+ if (height <= 0)
13350
13553
  return;
13351
13554
  top = this.$getTop(range.start.row + 1, config);
13555
+
13556
+ var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8);
13352
13557
 
13353
13558
  stringBuilder.push(
13354
- "<div class='", clazz, "' style='",
13559
+ "<div class='", clazz, (radiusClass ? " ace_br" + radiusClass : ""), "' style='",
13355
13560
  "height:", height, "px;",
13356
13561
  "right:0;",
13357
13562
  "top:", top, "px;",
@@ -13430,7 +13635,7 @@ var Text = function(parentEl) {
13430
13635
  this.EOL_CHAR_LF = "\xAC";
13431
13636
  this.EOL_CHAR_CRLF = "\xa4";
13432
13637
  this.EOL_CHAR = this.EOL_CHAR_LF;
13433
- this.TAB_CHAR = "\u2192"; //"\u21E5";
13638
+ this.TAB_CHAR = "\u2014"; //"\u21E5";
13434
13639
  this.SPACE_CHAR = "\xB7";
13435
13640
  this.$padding = 0;
13436
13641
 
@@ -13506,11 +13711,10 @@ var Text = function(parentEl) {
13506
13711
  for (var i = 1; i < tabSize + 1; i++) {
13507
13712
  if (this.showInvisibles) {
13508
13713
  tabStr.push("<span class='ace_invisible ace_invisible_tab'>"
13509
- + this.TAB_CHAR
13510
- + lang.stringRepeat("\xa0", i - 1)
13714
+ + lang.stringRepeat(this.TAB_CHAR, i)
13511
13715
  + "</span>");
13512
13716
  } else {
13513
- tabStr.push(lang.stringRepeat("\xa0", i));
13717
+ tabStr.push(lang.stringRepeat(" ", i));
13514
13718
  }
13515
13719
  }
13516
13720
  if (this.displayIndentGuides) {
@@ -13523,9 +13727,9 @@ var Text = function(parentEl) {
13523
13727
  spaceClass = " ace_invisible_space";
13524
13728
  tabClass = " ace_invisible_tab";
13525
13729
  var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);
13526
- var tabContent = this.TAB_CHAR + lang.stringRepeat("\xa0", this.tabSize - 1);
13730
+ var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize);
13527
13731
  } else{
13528
- var spaceContent = lang.stringRepeat("\xa0", this.tabSize);
13732
+ var spaceContent = lang.stringRepeat(" ", this.tabSize);
13529
13733
  var tabContent = spaceContent;
13530
13734
  }
13531
13735
 
@@ -13694,16 +13898,18 @@ var Text = function(parentEl) {
13694
13898
 
13695
13899
  this.$renderToken = function(stringBuilder, screenColumn, token, value) {
13696
13900
  var self = this;
13697
- var replaceReg = /\t|&|<|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g;
13901
+ var replaceReg = /\t|&|<|>|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g;
13698
13902
  var replaceFunc = function(c, a, b, tabIdx, idx4) {
13699
13903
  if (a) {
13700
- return self.showInvisibles ?
13701
- "<span class='ace_invisible ace_invisible_space'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>" :
13702
- lang.stringRepeat("\xa0", c.length);
13904
+ return self.showInvisibles
13905
+ ? "<span class='ace_invisible ace_invisible_space'>" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "</span>"
13906
+ : c;
13703
13907
  } else if (c == "&") {
13704
13908
  return "&#38;";
13705
13909
  } else if (c == "<") {
13706
13910
  return "&#60;";
13911
+ } else if (c == ">") {
13912
+ return "&#62;";
13707
13913
  } else if (c == "\t") {
13708
13914
  var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx);
13709
13915
  screenColumn += tabSize - 1;
@@ -13791,6 +13997,8 @@ var Text = function(parentEl) {
13791
13997
  );
13792
13998
  }
13793
13999
 
14000
+ stringBuilder.push(lang.stringRepeat("\xa0", splits.indent));
14001
+
13794
14002
  split ++;
13795
14003
  screenColumn = 0;
13796
14004
  splitChars = splits[split] || Number.MAX_VALUE;
@@ -13941,15 +14149,15 @@ define("ace/layer/cursor",["require","exports","module","ace/lib/dom"], function
13941
14149
  "use strict";
13942
14150
 
13943
14151
  var dom = require("../lib/dom");
13944
- var IE8;
14152
+ var isIE8;
13945
14153
 
13946
14154
  var Cursor = function(parentEl) {
13947
14155
  this.element = dom.createElement("div");
13948
14156
  this.element.className = "ace_layer ace_cursor-layer";
13949
14157
  parentEl.appendChild(this.element);
13950
14158
 
13951
- if (IE8 === undefined)
13952
- IE8 = "opacity" in this.element;
14159
+ if (isIE8 === undefined)
14160
+ isIE8 = !("opacity" in this.element.style);
13953
14161
 
13954
14162
  this.isVisible = false;
13955
14163
  this.isBlinking = true;
@@ -13959,7 +14167,9 @@ var Cursor = function(parentEl) {
13959
14167
  this.cursors = [];
13960
14168
  this.cursor = this.addCursor();
13961
14169
  dom.addCssClass(this.element, "ace_hidden-cursors");
13962
- this.$updateCursors = this.$updateVisibility.bind(this);
14170
+ this.$updateCursors = (isIE8
14171
+ ? this.$updateVisibility
14172
+ : this.$updateOpacity).bind(this);
13963
14173
  };
13964
14174
 
13965
14175
  (function() {
@@ -14000,13 +14210,11 @@ var Cursor = function(parentEl) {
14000
14210
  };
14001
14211
 
14002
14212
  this.setSmoothBlinking = function(smoothBlinking) {
14003
- if (smoothBlinking != this.smoothBlinking && !IE8) {
14213
+ if (smoothBlinking != this.smoothBlinking && !isIE8) {
14004
14214
  this.smoothBlinking = smoothBlinking;
14005
14215
  dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking);
14006
14216
  this.$updateCursors(true);
14007
- this.$updateCursors = (smoothBlinking
14008
- ? this.$updateOpacity
14009
- : this.$updateVisibility).bind(this);
14217
+ this.$updateCursors = (this.$updateOpacity).bind(this);
14010
14218
  this.restartTimer();
14011
14219
  }
14012
14220
  };
@@ -14398,9 +14606,9 @@ var FontMetrics = exports.FontMetrics = function(parentEl, interval) {
14398
14606
  this.setPolling = function(val) {
14399
14607
  if (val) {
14400
14608
  this.$pollSizeChanges();
14401
- } else {
14402
- if (this.$pollSizeChangesTimer)
14403
- this.$pollSizeChangesTimer;
14609
+ } else if (this.$pollSizeChangesTimer) {
14610
+ clearInterval(this.$pollSizeChangesTimer);
14611
+ this.$pollSizeChangesTimer = 0;
14404
14612
  }
14405
14613
  };
14406
14614
 
@@ -14598,6 +14806,7 @@ text-indent: -1em;\
14598
14806
  -moz-user-select: text;\
14599
14807
  -webkit-user-select: text;\
14600
14808
  user-select: text;\
14809
+ white-space: pre!important;\
14601
14810
  }\
14602
14811
  .ace_text-input.ace_composition {\
14603
14812
  background: inherit;\
@@ -14641,7 +14850,8 @@ position: absolute;\
14641
14850
  -moz-box-sizing: border-box;\
14642
14851
  -webkit-box-sizing: border-box;\
14643
14852
  box-sizing: border-box;\
14644
- border-left: 2px solid\
14853
+ border-left: 2px solid;\
14854
+ transform: translatez(0);\
14645
14855
  }\
14646
14856
  .ace_slim-cursors .ace_cursor {\
14647
14857
  border-left-width: 1px;\
@@ -14822,9 +15032,24 @@ background-color: rgba(255, 255, 0,0.2);\
14822
15032
  position: absolute;\
14823
15033
  z-index: 8;\
14824
15034
  }\
15035
+ .ace_br1 {border-top-left-radius : 3px;}\
15036
+ .ace_br2 {border-top-right-radius : 3px;}\
15037
+ .ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}\
15038
+ .ace_br4 {border-bottom-right-radius: 3px;}\
15039
+ .ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}\
15040
+ .ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}\
15041
+ .ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}\
15042
+ .ace_br8 {border-bottom-left-radius : 3px;}\
15043
+ .ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}\
15044
+ .ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}\
15045
+ .ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}\
15046
+ .ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\
15047
+ .ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\
15048
+ .ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\
15049
+ .ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}\
14825
15050
  ";
14826
15051
 
14827
- dom.importCssString(editorCss, "ace_editor");
15052
+ dom.importCssString(editorCss, "ace_editor.css");
14828
15053
 
14829
15054
  var VirtualRenderer = function(container, theme) {
14830
15055
  var _self = this;
@@ -15234,7 +15459,7 @@ var VirtualRenderer = function(container, theme) {
15234
15459
  return this.container;
15235
15460
  };
15236
15461
  this.getMouseEventTarget = function() {
15237
- return this.content;
15462
+ return this.scroller;
15238
15463
  };
15239
15464
  this.getTextAreaContainer = function() {
15240
15465
  return this.container;
@@ -15463,6 +15688,8 @@ var VirtualRenderer = function(container, theme) {
15463
15688
  (this.$minLines||1) * this.lineHeight,
15464
15689
  Math.min(maxHeight, height)
15465
15690
  ) + this.scrollMargin.v + (this.$extraHeight || 0);
15691
+ if (this.$horizScroll)
15692
+ desiredHeight += this.scrollBarH.getHeight();
15466
15693
  var vScroll = height > maxHeight;
15467
15694
 
15468
15695
  if (desiredHeight != this.desiredHeight ||
@@ -15482,9 +15709,6 @@ var VirtualRenderer = function(container, theme) {
15482
15709
  };
15483
15710
 
15484
15711
  this.$computeLayerConfig = function() {
15485
- if (this.$maxLines && this.lineHeight > 1)
15486
- this.$autosize();
15487
-
15488
15712
  var session = this.session;
15489
15713
  var size = this.$size;
15490
15714
 
@@ -15492,9 +15716,6 @@ var VirtualRenderer = function(container, theme) {
15492
15716
  var screenLines = this.session.getScreenLength();
15493
15717
  var maxHeight = screenLines * this.lineHeight;
15494
15718
 
15495
- var offset = this.scrollTop % this.lineHeight;
15496
- var minHeight = size.scrollerHeight + this.lineHeight;
15497
-
15498
15719
  var longestLine = this.$getLongestLine();
15499
15720
 
15500
15721
  var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible ||
@@ -15505,21 +15726,28 @@ var VirtualRenderer = function(container, theme) {
15505
15726
  this.$horizScroll = horizScroll;
15506
15727
  this.scrollBarH.setVisible(horizScroll);
15507
15728
  }
15729
+ var vScrollBefore = this.$vScroll; // autosize can change vscroll value in which case we need to update longestLine
15730
+ if (this.$maxLines && this.lineHeight > 1)
15731
+ this.$autosize();
15732
+
15733
+ var offset = this.scrollTop % this.lineHeight;
15734
+ var minHeight = size.scrollerHeight + this.lineHeight;
15508
15735
 
15509
15736
  var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd
15510
15737
  ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd
15511
15738
  : 0;
15512
15739
  maxHeight += scrollPastEnd;
15513
15740
 
15514
- this.session.setScrollTop(Math.max(-this.scrollMargin.top,
15515
- Math.min(this.scrollTop, maxHeight - size.scrollerHeight + this.scrollMargin.bottom)));
15741
+ var sm = this.scrollMargin;
15742
+ this.session.setScrollTop(Math.max(-sm.top,
15743
+ Math.min(this.scrollTop, maxHeight - size.scrollerHeight + sm.bottom)));
15516
15744
 
15517
- this.session.setScrollLeft(Math.max(-this.scrollMargin.left, Math.min(this.scrollLeft,
15518
- longestLine + 2 * this.$padding - size.scrollerWidth + this.scrollMargin.right)));
15745
+ this.session.setScrollLeft(Math.max(-sm.left, Math.min(this.scrollLeft,
15746
+ longestLine + 2 * this.$padding - size.scrollerWidth + sm.right)));
15519
15747
 
15520
15748
  var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible ||
15521
- size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop);
15522
- var vScrollChanged = this.$vScroll !== vScroll;
15749
+ size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop > sm.top);
15750
+ var vScrollChanged = vScrollBefore !== vScroll;
15523
15751
  if (vScrollChanged) {
15524
15752
  this.$vScroll = vScroll;
15525
15753
  this.scrollBarV.setVisible(vScroll);
@@ -16203,19 +16431,22 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) {
16203
16431
  doc.on("change", this.changeListener);
16204
16432
  };
16205
16433
 
16206
- this.changeListener = function(e) {
16434
+ this.changeListener = function(delta) {
16207
16435
  if (!this.deltaQueue) {
16208
- this.deltaQueue = [e.data];
16436
+ this.deltaQueue = [];
16209
16437
  setTimeout(this.$sendDeltaQueue, 0);
16210
- } else
16211
- this.deltaQueue.push(e.data);
16438
+ }
16439
+ if (delta.action == "insert")
16440
+ this.deltaQueue.push(delta.start, delta.lines);
16441
+ else
16442
+ this.deltaQueue.push(delta.start, delta.end);
16212
16443
  };
16213
16444
 
16214
16445
  this.$sendDeltaQueue = function() {
16215
16446
  var q = this.deltaQueue;
16216
16447
  if (!q) return;
16217
16448
  this.deltaQueue = null;
16218
- if (q.length > 20 && q.length > this.$doc.getLength() >> 1) {
16449
+ if (q.length > 50 && q.length > this.$doc.getLength() >> 1) {
16219
16450
  this.call("setValue", [this.$doc.getValue()]);
16220
16451
  } else
16221
16452
  this.emit("change", {data: q});
@@ -16371,28 +16602,27 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
16371
16602
  this.session.removeMarker(this.others[i].markerId);
16372
16603
  }
16373
16604
  };
16374
- this.onUpdate = function(event) {
16375
- var delta = event.data;
16376
- var range = delta.range;
16605
+ this.onUpdate = function(delta) {
16606
+ var range = delta;
16377
16607
  if(range.start.row !== range.end.row) return;
16378
16608
  if(range.start.row !== this.pos.row) return;
16379
16609
  if (this.$updating) return;
16380
16610
  this.$updating = true;
16381
- var lengthDiff = delta.action === "insertText" ? range.end.column - range.start.column : range.start.column - range.end.column;
16611
+ var lengthDiff = delta.action === "insert" ? range.end.column - range.start.column : range.start.column - range.end.column;
16382
16612
 
16383
16613
  if(range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1) {
16384
16614
  var distanceFromStart = range.start.column - this.pos.column;
16385
16615
  this.length += lengthDiff;
16386
16616
  if(!this.session.$fromUndo) {
16387
- if(delta.action === "insertText") {
16617
+ if(delta.action === 'insert') {
16388
16618
  for (var i = this.others.length - 1; i >= 0; i--) {
16389
16619
  var otherPos = this.others[i];
16390
16620
  var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
16391
16621
  if(otherPos.row === range.start.row && range.start.column < otherPos.column)
16392
16622
  newPos.column += lengthDiff;
16393
- this.doc.insert(newPos, delta.text);
16623
+ this.doc.insertMergedLines(newPos, delta.lines);
16394
16624
  }
16395
- } else if(delta.action === "removeText") {
16625
+ } else if(delta.action === 'remove') {
16396
16626
  for (var i = this.others.length - 1; i >= 0; i--) {
16397
16627
  var otherPos = this.others[i];
16398
16628
  var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
@@ -16401,7 +16631,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
16401
16631
  this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff));
16402
16632
  }
16403
16633
  }
16404
- if(range.start.column === this.pos.column && delta.action === "insertText") {
16634
+ if(range.start.column === this.pos.column && delta.action === 'insert') {
16405
16635
  setTimeout(function() {
16406
16636
  this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff);
16407
16637
  for (var i = 0; i < this.others.length; i++) {
@@ -16413,7 +16643,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
16413
16643
  }
16414
16644
  }.bind(this), 0);
16415
16645
  }
16416
- else if(range.start.column === this.pos.column && delta.action === "removeText") {
16646
+ else if(range.start.column === this.pos.column && delta.action === 'remove') {
16417
16647
  setTimeout(function() {
16418
16648
  for (var i = 0; i < this.others.length; i++) {
16419
16649
  var other = this.others[i];
@@ -16525,15 +16755,15 @@ function onMouseDown(e) {
16525
16755
  var selectionMode;
16526
16756
  if (editor.$mouseHandler.$enableJumpToDef) {
16527
16757
  if (ctrl && alt || accel && alt)
16528
- selectionMode = "add";
16529
- else if (alt)
16758
+ selectionMode = shift ? "block" : "add";
16759
+ else if (alt && editor.$blockSelectEnabled)
16530
16760
  selectionMode = "block";
16531
16761
  } else {
16532
16762
  if (accel && !alt) {
16533
16763
  selectionMode = "add";
16534
16764
  if (!isMultiSelect && shift)
16535
16765
  return;
16536
- } else if (alt) {
16766
+ } else if (alt && editor.$blockSelectEnabled) {
16537
16767
  selectionMode = "block";
16538
16768
  }
16539
16769
  }
@@ -16559,7 +16789,7 @@ function onMouseDown(e) {
16559
16789
 
16560
16790
  if (shift) {
16561
16791
  oldRange = null;
16562
- range = selection.ranges[0];
16792
+ range = selection.ranges[0] || range;
16563
16793
  editor.removeSelectionMarker(range);
16564
16794
  }
16565
16795
  editor.once("mouseup", function() {
@@ -16658,54 +16888,54 @@ exports.defaultCommands = [{
16658
16888
  exec: function(editor) { editor.selectMoreLines(-1); },
16659
16889
  bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"},
16660
16890
  scrollIntoView: "cursor",
16661
- readonly: true
16891
+ readOnly: true
16662
16892
  }, {
16663
16893
  name: "addCursorBelow",
16664
16894
  exec: function(editor) { editor.selectMoreLines(1); },
16665
16895
  bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
16666
16896
  scrollIntoView: "cursor",
16667
- readonly: true
16897
+ readOnly: true
16668
16898
  }, {
16669
16899
  name: "addCursorAboveSkipCurrent",
16670
16900
  exec: function(editor) { editor.selectMoreLines(-1, true); },
16671
16901
  bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
16672
16902
  scrollIntoView: "cursor",
16673
- readonly: true
16903
+ readOnly: true
16674
16904
  }, {
16675
16905
  name: "addCursorBelowSkipCurrent",
16676
16906
  exec: function(editor) { editor.selectMoreLines(1, true); },
16677
16907
  bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
16678
16908
  scrollIntoView: "cursor",
16679
- readonly: true
16909
+ readOnly: true
16680
16910
  }, {
16681
16911
  name: "selectMoreBefore",
16682
16912
  exec: function(editor) { editor.selectMore(-1); },
16683
16913
  bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"},
16684
16914
  scrollIntoView: "cursor",
16685
- readonly: true
16915
+ readOnly: true
16686
16916
  }, {
16687
16917
  name: "selectMoreAfter",
16688
16918
  exec: function(editor) { editor.selectMore(1); },
16689
16919
  bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"},
16690
16920
  scrollIntoView: "cursor",
16691
- readonly: true
16921
+ readOnly: true
16692
16922
  }, {
16693
16923
  name: "selectNextBefore",
16694
16924
  exec: function(editor) { editor.selectMore(-1, true); },
16695
16925
  bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"},
16696
16926
  scrollIntoView: "cursor",
16697
- readonly: true
16927
+ readOnly: true
16698
16928
  }, {
16699
16929
  name: "selectNextAfter",
16700
16930
  exec: function(editor) { editor.selectMore(1, true); },
16701
16931
  bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"},
16702
16932
  scrollIntoView: "cursor",
16703
- readonly: true
16933
+ readOnly: true
16704
16934
  }, {
16705
16935
  name: "splitIntoLines",
16706
16936
  exec: function(editor) { editor.multiSelect.splitIntoLines(); },
16707
16937
  bindKey: {win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L"},
16708
- readonly: true
16938
+ readOnly: true
16709
16939
  }, {
16710
16940
  name: "alignCursors",
16711
16941
  exec: function(editor) { editor.alignCursors(); },
@@ -16716,14 +16946,14 @@ exports.defaultCommands = [{
16716
16946
  exec: function(editor) { editor.findAll(); },
16717
16947
  bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"},
16718
16948
  scrollIntoView: "cursor",
16719
- readonly: true
16949
+ readOnly: true
16720
16950
  }];
16721
16951
  exports.multiSelectCommands = [{
16722
16952
  name: "singleSelection",
16723
16953
  bindKey: "esc",
16724
16954
  exec: function(editor) { editor.exitMultiSelectMode(); },
16725
16955
  scrollIntoView: "cursor",
16726
- readonly: true,
16956
+ readOnly: true,
16727
16957
  isAvailable: function(editor) {return editor && editor.inMultiSelectMode}
16728
16958
  }];
16729
16959
 
@@ -17325,9 +17555,9 @@ var Editor = require("./editor").Editor;
17325
17555
  if (fr < 0) fr = 0;
17326
17556
  if (lr >= max) lr = max - 1;
17327
17557
  }
17328
- var lines = this.session.doc.removeLines(fr, lr);
17558
+ var lines = this.session.removeFullLines(fr, lr);
17329
17559
  lines = this.$reAlignText(lines, guessRange);
17330
- this.session.doc.insert({row: fr, column: 0}, lines.join("\n") + "\n");
17560
+ this.session.insert({row: fr, column: 0}, lines.join("\n") + "\n");
17331
17561
  if (!guessRange) {
17332
17562
  range.start.column = 0;
17333
17563
  range.end.column = lines[lines.length - 1].length;
@@ -17488,7 +17718,8 @@ function addAltCursorListeners(editor){
17488
17718
  var el = editor.textInput.getElement();
17489
17719
  var altCursor = false;
17490
17720
  event.addListener(el, "keydown", function(e) {
17491
- if (e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey)) {
17721
+ var altDown = e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey);
17722
+ if (editor.$blockSelectEnabled && altDown) {
17492
17723
  if (!altCursor) {
17493
17724
  editor.renderer.setMouseCursor("crosshair");
17494
17725
  altCursor = true;
@@ -17524,6 +17755,12 @@ require("./config").defineOptions(Editor.prototype, "editor", {
17524
17755
  }
17525
17756
  },
17526
17757
  value: true
17758
+ },
17759
+ enableBlockSelect: {
17760
+ set: function(val) {
17761
+ this.$blockSelectEnabled = val;
17762
+ },
17763
+ value: true
17527
17764
  }
17528
17765
  });
17529
17766
 
@@ -17720,7 +17957,6 @@ background: rgb(181, 213, 255);\
17720
17957
  }\
17721
17958
  .ace-tm.ace_multiselect .ace_selection.ace_start {\
17722
17959
  box-shadow: 0 0 3px 0px white;\
17723
- border-radius: 2px;\
17724
17960
  }\
17725
17961
  .ace-tm .ace_marker-layer .ace_step {\
17726
17962
  background: rgb(252, 255, 0);\
@@ -17836,17 +18072,15 @@ function LineWidgets(session) {
17836
18072
  });
17837
18073
  };
17838
18074
 
17839
- this.updateOnChange = function(e) {
18075
+ this.updateOnChange = function(delta) {
17840
18076
  var lineWidgets = this.session.lineWidgets;
17841
18077
  if (!lineWidgets) return;
17842
-
17843
- var delta = e.data;
17844
- var range = delta.range;
17845
- var startRow = range.start.row;
17846
- var len = range.end.row - startRow;
18078
+
18079
+ var startRow = delta.start.row;
18080
+ var len = delta.end.row - startRow;
17847
18081
 
17848
18082
  if (len === 0) {
17849
- } else if (delta.action == "removeText" || delta.action == "removeLines") {
18083
+ } else if (delta.action == 'remove') {
17850
18084
  var removed = lineWidgets.splice(startRow + 1, len);
17851
18085
  removed.forEach(function(w) {
17852
18086
  w && this.removeLineWidget(w);
@@ -18236,7 +18470,7 @@ exports.edit = function(el) {
18236
18470
  value = oldNode.value;
18237
18471
  el = dom.createElement("pre");
18238
18472
  oldNode.parentNode.replaceChild(el, oldNode);
18239
- } else {
18473
+ } else if (el) {
18240
18474
  value = dom.getInnerText(el);
18241
18475
  el.innerHTML = '';
18242
18476
  }