formagic 0.1.0 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
  }