Compare commits
No commits in common. "master" and "fix/leak" have entirely different histories.
89 changed files with 748 additions and 1937 deletions
|
|
@ -1,16 +1,5 @@
|
|||
Version 1.2.0-pre
|
||||
|
||||
* New Features
|
||||
- Indented soft wrap (danyaPostfactum)
|
||||
|
||||
* API Changes
|
||||
- unified delta types `{start, end, action, lines}` (Alden Daniels https://github.com/ajaxorg/ace/pull/1745)
|
||||
- "change" event listeners on session and editor get delta objects directly
|
||||
|
||||
2015.04.03 Version 1.1.9
|
||||
|
||||
- Small Enhancements and Bugfixes
|
||||
|
||||
2014.11.08 Version 1.1.8
|
||||
|
||||
* API Changes
|
||||
|
|
|
|||
2
build
2
build
|
|
@ -1 +1 @@
|
|||
Subproject commit a4e495d8901876c6bafe3870a35cb8e32c827e97
|
||||
Subproject commit e3ccd2c654cf45ee41ffb09d0e7fa5b40cf91a8f
|
||||
|
|
@ -7,13 +7,14 @@
|
|||
<style type="text/css" media="screen">
|
||||
|
||||
.ace_editor {
|
||||
position: relative !important;
|
||||
border: 1px solid lightgray;
|
||||
margin: auto;
|
||||
height: 200px;
|
||||
width: 80%;
|
||||
}
|
||||
.scrollmargin {
|
||||
height: 80px;
|
||||
height: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -23,8 +24,6 @@
|
|||
<div class="scrollmargin"></div>
|
||||
<pre id="editor2">minHeight = 2 lines</pre>
|
||||
<div class="scrollmargin"></div>
|
||||
<pre id="editor3" style="width: 40%;"></pre>
|
||||
<div class="scrollmargin"></div>
|
||||
<pre id="editor"></pre>
|
||||
|
||||
<script src="kitchen-sink/require.js"></script>
|
||||
|
|
@ -47,13 +46,6 @@ require(["ace/ace"], function(ace) {
|
|||
editor2.setOption("maxLines", 30);
|
||||
editor2.setOption("minLines", 2);
|
||||
|
||||
var editor = ace.edit("editor3");
|
||||
editor.setOptions({
|
||||
autoScrollEditorIntoView: true,
|
||||
maxLines: 8
|
||||
});
|
||||
editor.renderer.setScrollMargin(10, 10, 10, 10);
|
||||
|
||||
var editor = ace.edit("editor");
|
||||
editor.setTheme("ace/theme/tomorrow");
|
||||
editor.session.setMode("ace/mode/html");
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ function warn() {
|
|||
s.shift(); // remove the getter
|
||||
s = s.join("\n");
|
||||
// allow easy access to ace in console, but not in ace code
|
||||
if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}|\(<anonymous>:\d+:\d+\)/.test(s)) {
|
||||
if (!/at Object.InjectedScript.|@debugger eval|snippets:\/{3}/.test(s)) {
|
||||
console.error("trying to access to global variable");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@
|
|||
* Simple node.js server, which generates the synax highlighted version of itself
|
||||
* using the Ace modes and themes on the server and serving a static web page.
|
||||
*/
|
||||
|
||||
// $'
|
||||
// include ace search path and modules
|
||||
require("amd-loader");
|
||||
|
||||
// load jsdom, which is required by Ace
|
||||
require("../../lib/ace/test/mockdom");
|
||||
|
||||
var http = require("http");
|
||||
var fs = require("fs");
|
||||
var resolve = require("path").resolve;
|
||||
|
||||
// load the highlighter and the desired mode and theme
|
||||
var highlighter = require("../../lib/ace/ext/static_highlight");
|
||||
|
|
@ -18,22 +20,15 @@ var theme = require("../../lib/ace/theme/twilight");
|
|||
var port = process.env.PORT || 2222;
|
||||
|
||||
http.createServer(function(req, res) {
|
||||
var url = req.url;
|
||||
var path = /[^#?\x00]*/.exec(url)[0];
|
||||
var root = resolve(__dirname + "/../../").replace(/\\/g, "/");
|
||||
path = resolve(root + "/" + path).replace(/\\/g, "/");
|
||||
if (path.indexOf(root + "/") != 0)
|
||||
path = __filename;
|
||||
res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"});
|
||||
fs.readFile(path, "utf8", function(err, data) {
|
||||
if (err) data = err.message;
|
||||
fs.readFile(__dirname + "/../../build/src/ace.js", "utf8", function(err, data) {
|
||||
var highlighted = highlighter.render(data, new JavaScriptMode(), theme);
|
||||
res.end(
|
||||
'<html><body>\n' +
|
||||
'<style type="text/css" media="screen">\n' +
|
||||
highlighted.css +
|
||||
'</style>\n' +
|
||||
highlighted.html +
|
||||
highlighted.html +
|
||||
'</body></html>'
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -99,54 +99,72 @@ var Anchor = exports.Anchor = function(doc, row, column) {
|
|||
* - `value`: An object describing the new Anchor position
|
||||
*
|
||||
**/
|
||||
this.onChange = function(delta) {
|
||||
if (delta.start.row == delta.end.row && delta.start.row != this.row)
|
||||
this.onChange = function(e) {
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
|
||||
if (range.start.row == range.end.row && range.start.row != this.row)
|
||||
return;
|
||||
|
||||
if (delta.start.row > this.row)
|
||||
if (range.start.row > this.row)
|
||||
return;
|
||||
|
||||
var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight);
|
||||
this.setPosition(point.row, point.column, true);
|
||||
|
||||
if (range.start.row == this.row && range.start.column > this.column)
|
||||
return;
|
||||
|
||||
var row = this.row;
|
||||
var column = this.column;
|
||||
var start = range.start;
|
||||
var end = range.end;
|
||||
|
||||
if (delta.action === "insertText") {
|
||||
if (start.row === row && start.column <= column) {
|
||||
if (start.column === column && this.$insertRight) {
|
||||
// do nothing
|
||||
} else if (start.row === end.row) {
|
||||
column += end.column - start.column;
|
||||
} else {
|
||||
column -= start.column;
|
||||
row += end.row - start.row;
|
||||
}
|
||||
} else if (start.row !== end.row && start.row < row) {
|
||||
row += end.row - start.row;
|
||||
}
|
||||
} else if (delta.action === "insertLines") {
|
||||
if (start.row === row && column === 0 && this.$insertRight) {
|
||||
// do nothing
|
||||
}
|
||||
else if (start.row <= row) {
|
||||
row += end.row - start.row;
|
||||
}
|
||||
} else if (delta.action === "removeText") {
|
||||
if (start.row === row && start.column < column) {
|
||||
if (end.column >= column)
|
||||
column = start.column;
|
||||
else
|
||||
column = Math.max(0, column - (end.column - start.column));
|
||||
|
||||
} else if (start.row !== end.row && start.row < row) {
|
||||
if (end.row === row)
|
||||
column = Math.max(0, column - end.column) + start.column;
|
||||
row -= (end.row - start.row);
|
||||
} else if (end.row === row) {
|
||||
row -= end.row - start.row;
|
||||
column = Math.max(0, column - end.column) + start.column;
|
||||
}
|
||||
} else if (delta.action == "removeLines") {
|
||||
if (start.row <= row) {
|
||||
if (end.row <= row)
|
||||
row -= end.row - start.row;
|
||||
else {
|
||||
row = start.row;
|
||||
column = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setPosition(row, column, true);
|
||||
};
|
||||
|
||||
function $pointsInOrder(point1, point2, equalPointsInOrder) {
|
||||
var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column;
|
||||
return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter);
|
||||
}
|
||||
|
||||
function $getTransformedPoint(delta, point, moveIfEqual) {
|
||||
// Get delta info.
|
||||
var deltaIsInsert = delta.action == "insert";
|
||||
var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row);
|
||||
var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column);
|
||||
var deltaStart = delta.start;
|
||||
var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range.
|
||||
|
||||
// DELTA AFTER POINT: No change needed.
|
||||
if ($pointsInOrder(point, deltaStart, moveIfEqual)) {
|
||||
return {
|
||||
row: point.row,
|
||||
column: point.column
|
||||
};
|
||||
}
|
||||
|
||||
// DELTA BEFORE POINT: Move point by delta shift.
|
||||
if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) {
|
||||
return {
|
||||
row: point.row + deltaRowShift,
|
||||
column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0)
|
||||
};
|
||||
}
|
||||
|
||||
// DELTA ENVELOPS POINT (delete only): Move point to delta start.
|
||||
// TODO warn if delta.action != "remove" ?
|
||||
|
||||
return {
|
||||
row: deltaStart.row,
|
||||
column: deltaStart.column
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the anchor position to the specified row and column. If `noClip` is `true`, the position is not clipped.
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insertFullLines(1, ["123", "456"]);
|
||||
doc.insertLines(1, ["123", "456"]);
|
||||
assert.position(anchor.getPosition(), 3, 4);
|
||||
},
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insertMergedLines({row: 0, column: 0}, ['', '']);
|
||||
doc.insertNewLine({row: 0, column: 0});
|
||||
assert.position(anchor.getPosition(), 2, 4);
|
||||
},
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners");
|
||||
var anchor = new Anchor(doc, 1, 4);
|
||||
|
||||
doc.insertMergedLines({row: 1, column: 2}, ['', '']);
|
||||
doc.insertNewLine({row: 1, column: 2});
|
||||
assert.position(anchor.getPosition(), 2, 2);
|
||||
},
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\n1\n2\nkinners");
|
||||
var anchor = new Anchor(doc, 3, 4);
|
||||
|
||||
doc.removeFullLines(1, 2);
|
||||
doc.removeLines(1, 2);
|
||||
assert.position(anchor.getPosition(), 1, 4);
|
||||
},
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners\n123");
|
||||
var anchor = new Anchor(doc, 1, 5);
|
||||
|
||||
doc.removeFullLines(1, 1);
|
||||
doc.removeLines(1, 1);
|
||||
assert.position(anchor.getPosition(), 1, 0);
|
||||
},
|
||||
|
||||
|
|
@ -208,9 +208,9 @@ module.exports = {
|
|||
var doc = new Document("juhu\nkinners\n123");
|
||||
var anchor = new Anchor(doc, 2, 4);
|
||||
|
||||
doc.removeFullLines(0, 3);
|
||||
doc.removeLines(0, 3);
|
||||
assert.position(anchor.getPosition(), 0, 0);
|
||||
doc.insertFullLines(0, ["a", "b", "c"]);
|
||||
doc.insertLines(0, ["a", "b", "c"]);
|
||||
assert.position(anchor.getPosition(), 3, 0);
|
||||
assert.equal(doc.getValue(), "a\nb\nc\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2010, Ajax.org B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ajax.org B.V. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
function throwDeltaError(delta, errorText){
|
||||
console.log("Invalid Delta:", delta);
|
||||
throw "Invalid Delta: " + errorText;
|
||||
}
|
||||
|
||||
function positionInDocument(docLines, position) {
|
||||
return position.row >= 0 && position.row < docLines.length &&
|
||||
position.column >= 0 && position.column <= docLines[position.row].length;
|
||||
}
|
||||
|
||||
function validateDelta(docLines, delta) {
|
||||
// Validate action string.
|
||||
if (delta.action != "insert" && delta.action != "remove")
|
||||
throwDeltaError(delta, "delta.action must be 'insert' or 'remove'");
|
||||
|
||||
// Validate lines type.
|
||||
if (!(delta.lines instanceof Array))
|
||||
throwDeltaError(delta, "delta.lines must be an Array");
|
||||
|
||||
// Validate range type.
|
||||
if (!delta.start || !delta.end)
|
||||
throwDeltaError(delta, "delta.start/end must be an present");
|
||||
|
||||
// Validate that the start point is contained in the document.
|
||||
var start = delta.start;
|
||||
if (!positionInDocument(docLines, delta.start))
|
||||
throwDeltaError(delta, "delta.start must be contained in document");
|
||||
|
||||
// Validate that the end point is contained in the document (remove deltas only).
|
||||
var end = delta.end;
|
||||
if (delta.action == "remove" && !positionInDocument(docLines, end))
|
||||
throwDeltaError(delta, "delta.end must contained in document for 'remove' actions");
|
||||
|
||||
// Validate that the .range size matches the .lines size.
|
||||
var numRangeRows = end.row - start.row;
|
||||
var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0));
|
||||
if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars)
|
||||
throwDeltaError(delta, "delta.range must match delta lines");
|
||||
}
|
||||
|
||||
exports.applyDelta = function(docLines, delta, doNotValidate) {
|
||||
// disabled validation since it breaks autocompletion popup
|
||||
// if (!doNotValidate)
|
||||
// validateDelta(docLines, delta);
|
||||
|
||||
var row = delta.start.row;
|
||||
var startColumn = delta.start.column;
|
||||
var line = docLines[row] || "";
|
||||
switch (delta.action) {
|
||||
case "insert":
|
||||
var lines = delta.lines;
|
||||
if (lines.length === 1) {
|
||||
docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn);
|
||||
} else {
|
||||
var args = [row, 1].concat(delta.lines);
|
||||
docLines.splice.apply(docLines, args);
|
||||
docLines[row] = line.substring(0, startColumn) + docLines[row];
|
||||
docLines[row + delta.lines.length - 1] += line.substring(startColumn);
|
||||
}
|
||||
break;
|
||||
case "remove":
|
||||
var endColumn = delta.end.column;
|
||||
var endRow = delta.end.row;
|
||||
if (row === endRow) {
|
||||
docLines[row] = line.substring(0, startColumn) + line.substring(endColumn);
|
||||
} else {
|
||||
docLines.splice(
|
||||
row, endRow - row + 1,
|
||||
line.substring(0, startColumn) + docLines[endRow].substring(endColumn)
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -100,7 +100,7 @@ var Autocomplete = function() {
|
|||
var rect = editor.container.getBoundingClientRect();
|
||||
pos.top += rect.top - renderer.layerConfig.offset;
|
||||
pos.left += rect.left - editor.renderer.scrollLeft;
|
||||
pos.left += renderer.gutterWidth;
|
||||
pos.left += renderer.$gutterLayer.gutterWidth;
|
||||
|
||||
this.popup.show(pos, lineHeight);
|
||||
} else if (keepPopupPosition && !prefix) {
|
||||
|
|
@ -142,11 +142,10 @@ var Autocomplete = function() {
|
|||
// we have to check if activeElement is a child of popup because
|
||||
// on IE preventDefault doesn't stop scrollbar from being focussed
|
||||
var el = document.activeElement;
|
||||
var text = this.editor.textInput.getElement();
|
||||
var fromTooltip = e.relatedTarget && e.relatedTarget == this.tooltipNode;
|
||||
var container = this.popup && this.popup.container;
|
||||
if (el != text && el.parentNode != container && !fromTooltip
|
||||
&& el != this.tooltipNode && e.relatedTarget != text
|
||||
var text = this.editor.textInput.getElement()
|
||||
if (el != text && ( !this.popup || el.parentNode != this.popup.container )
|
||||
&& el != this.tooltipNode && e.relatedTarget != this.tooltipNode
|
||||
&& e.relatedTarget != text
|
||||
) {
|
||||
this.detach();
|
||||
}
|
||||
|
|
@ -350,7 +349,7 @@ var Autocomplete = function() {
|
|||
doc = selected;
|
||||
|
||||
if (typeof doc == "string")
|
||||
doc = {docText: doc};
|
||||
doc = {docText: doc}
|
||||
if (!doc || !(doc.docHTML || doc.docText))
|
||||
return this.hideDocTooltip();
|
||||
this.showDocTooltip(doc);
|
||||
|
|
@ -417,7 +416,7 @@ Autocomplete.startCommand = {
|
|||
bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"
|
||||
};
|
||||
|
||||
var FilteredList = function(array, filterText) {
|
||||
var FilteredList = function(array, filterText, mutateData) {
|
||||
this.all = array;
|
||||
this.filtered = array;
|
||||
this.filterText = filterText || "";
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var EditSession = require("../edit_session").EditSession;
|
||||
var Renderer = require("../virtual_renderer").VirtualRenderer;
|
||||
var Editor = require("../editor").Editor;
|
||||
var Range = require("../range").Range;
|
||||
|
|
@ -220,8 +221,8 @@ var AcePopup = function(parentNode) {
|
|||
|
||||
popup.data = [];
|
||||
popup.setData = function(list) {
|
||||
popup.setValue(lang.stringRepeat("\n", list.length), -1);
|
||||
popup.data = list || [];
|
||||
popup.setValue(lang.stringRepeat("\n", list.length), -1);
|
||||
popup.setRow(0);
|
||||
};
|
||||
popup.getData = function(row) {
|
||||
|
|
|
|||
|
|
@ -68,10 +68,11 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||
var endLine = -1;
|
||||
var doc = self.doc;
|
||||
|
||||
var startLine = currentLine;
|
||||
while (self.lines[currentLine])
|
||||
currentLine++;
|
||||
|
||||
|
||||
var startLine = currentLine;
|
||||
|
||||
var len = doc.getLength();
|
||||
var processedLines = 0;
|
||||
self.running = false;
|
||||
|
|
@ -171,12 +172,13 @@ var BackgroundTokenizer = function(tokenizer, editor) {
|
|||
}
|
||||
|
||||
this.$updateOnChange = function(delta) {
|
||||
var startRow = delta.start.row;
|
||||
var len = delta.end.row - startRow;
|
||||
var range = delta.range;
|
||||
var startRow = range.start.row;
|
||||
var len = range.end.row - startRow;
|
||||
|
||||
if (len === 0) {
|
||||
this.lines[startRow] = null;
|
||||
} else if (delta.action == "remove") {
|
||||
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
||||
this.lines.splice(startRow, len + 1, null);
|
||||
this.states.splice(startRow, len + 1, null);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -75,49 +75,6 @@ module.exports = {
|
|||
|
||||
forceTokenize(doc)
|
||||
testStates(doc, ["comment_regex_allowed", "start", "no_regex"])
|
||||
},
|
||||
"test background tokenizer sends update event" : function() {
|
||||
var doc = new EditSession([
|
||||
"/*",
|
||||
"var",
|
||||
"juhu",
|
||||
"*/"
|
||||
]);
|
||||
doc.setMode("./mode/javascript");
|
||||
|
||||
var updateEvent = null;
|
||||
doc.bgTokenizer.on("update", function(e) {
|
||||
updateEvent = e.data;
|
||||
});
|
||||
function checkEvent(first, last) {
|
||||
assert.ok(!updateEvent, "unneccessary update event");
|
||||
doc.bgTokenizer.running = 1;
|
||||
doc.bgTokenizer.$worker();
|
||||
assert.ok(updateEvent);
|
||||
assert.equal([first, last] + "",
|
||||
[updateEvent.first, updateEvent.last] + "")
|
||||
updateEvent = null;
|
||||
}
|
||||
|
||||
forceTokenize(doc);
|
||||
var comment = "comment_regex_allowed";
|
||||
testStates(doc, [comment, comment, comment, "start"]);
|
||||
|
||||
doc.remove(new Range(0,0,0,2));
|
||||
testStates(doc, [comment, comment, comment, "start"]);
|
||||
|
||||
checkEvent(0, 3);
|
||||
testStates(doc, ["start", "no_regex", "no_regex", "regex"]);
|
||||
|
||||
// insert /* and and press down several times quickly
|
||||
doc.insert({row:0, column:0}, "/*");
|
||||
doc.getTokens(0);
|
||||
doc.getTokens(1);
|
||||
doc.getTokens(2);
|
||||
checkEvent(0, 3);
|
||||
|
||||
forceTokenize(doc);
|
||||
testStates(doc, [comment, comment, comment, "start"]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -423,12 +423,6 @@ exports.commands = [{
|
|||
exec: function() {},
|
||||
passEvent: true,
|
||||
readOnly: true
|
||||
}, {
|
||||
name: "copy",
|
||||
exec: function(editor) {
|
||||
// placeholder for replay macro
|
||||
},
|
||||
readOnly: true
|
||||
},
|
||||
|
||||
// commands disabled in readOnly mode
|
||||
|
|
@ -445,12 +439,6 @@ exports.commands = [{
|
|||
},
|
||||
scrollIntoView: "cursor",
|
||||
multiSelectAction: "forEach"
|
||||
}, {
|
||||
name: "paste",
|
||||
exec: function(editor, args) {
|
||||
editor.$handlePaste(args);
|
||||
},
|
||||
scrollIntoView: "cursor"
|
||||
}, {
|
||||
name: "removeline",
|
||||
bindKey: bindKey("Ctrl-D", "Command-D"),
|
||||
|
|
|
|||
|
|
@ -422,30 +422,3 @@
|
|||
position: absolute;
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
/*
|
||||
styles = []
|
||||
for (var i = 1; i < 16; i++) {
|
||||
styles.push(".ace_br" + i + "{" + (
|
||||
["top-left", "top-right", "bottom-right", "bottom-left"]
|
||||
).map(function(x, j) {
|
||||
return i & (1<<j) ? "border-" + x + "-radius: 3px;" : ""
|
||||
}).filter(Boolean).join(" ") + "}")
|
||||
}
|
||||
styles.join("\n")
|
||||
*/
|
||||
.ace_br1 {border-top-left-radius : 3px;}
|
||||
.ace_br2 {border-top-right-radius : 3px;}
|
||||
.ace_br3 {border-top-left-radius : 3px; border-top-right-radius: 3px;}
|
||||
.ace_br4 {border-bottom-right-radius: 3px;}
|
||||
.ace_br5 {border-top-left-radius : 3px; border-bottom-right-radius: 3px;}
|
||||
.ace_br6 {border-top-right-radius : 3px; border-bottom-right-radius: 3px;}
|
||||
.ace_br7 {border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px;}
|
||||
.ace_br8 {border-bottom-left-radius : 3px;}
|
||||
.ace_br9 {border-top-left-radius : 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br10{border-top-right-radius : 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br11{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br12{border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br13{border-top-left-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br14{border-top-right-radius : 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
.ace_br15{border-top-left-radius : 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;}
|
||||
|
|
|
|||
|
|
@ -32,36 +32,36 @@ define(function(require, exports, module) {
|
|||
"use strict";
|
||||
|
||||
var oop = require("./lib/oop");
|
||||
var applyDelta = require("./apply_delta").applyDelta;
|
||||
var EventEmitter = require("./lib/event_emitter").EventEmitter;
|
||||
var Range = require("./range").Range;
|
||||
var Anchor = require("./anchor").Anchor;
|
||||
|
||||
/**
|
||||
* Contains the text of the document. Document can be attached to several [[EditSession `EditSession`]]s.
|
||||
*
|
||||
* At its core, `Document`s are just an array of strings, with each row in the document matching up to the array index.
|
||||
*
|
||||
* @class Document
|
||||
**/
|
||||
|
||||
/**
|
||||
/**
|
||||
*
|
||||
* Creates a new `Document`. If `text` is included, the `Document` contains those strings; otherwise, it's empty.
|
||||
* @param {String | Array} text The starting text
|
||||
* @constructor
|
||||
**/
|
||||
|
||||
var Document = function(textOrLines) {
|
||||
this.$lines = [""];
|
||||
var Document = function(text) {
|
||||
this.$lines = [];
|
||||
|
||||
// There has to be one line at least in the document. If you pass an empty
|
||||
// string to the insert function, nothing will happen. Workaround.
|
||||
if (textOrLines.length === 0) {
|
||||
if (text.length === 0) {
|
||||
this.$lines = [""];
|
||||
} else if (Array.isArray(textOrLines)) {
|
||||
this.insertMergedLines({row: 0, column: 0}, textOrLines);
|
||||
} else if (Array.isArray(text)) {
|
||||
this._insertLines(0, text);
|
||||
} else {
|
||||
this.insert({row: 0, column:0}, textOrLines);
|
||||
this.insert({row: 0, column:0}, text);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -75,9 +75,9 @@ var Document = function(textOrLines) {
|
|||
* @param {String} text The text to use
|
||||
**/
|
||||
this.setValue = function(text) {
|
||||
var len = this.getLength() - 1;
|
||||
this.remove(new Range(0, 0, len, this.getLine(len).length));
|
||||
this.insert({row: 0, column: 0}, text);
|
||||
var len = this.getLength();
|
||||
this.remove(new Range(0, 0, len, this.getLine(len-1).length));
|
||||
this.insert({row: 0, column:0}, text);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -98,7 +98,7 @@ var Document = function(textOrLines) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Splits a string of text on any newline (`\n`) or carriage-return (`\r`) characters.
|
||||
* Splits a string of text on any newline (`\n`) or carriage-return ('\r') characters.
|
||||
*
|
||||
* @method $split
|
||||
* @param {String} text The text to work with
|
||||
|
|
@ -107,15 +107,14 @@ var Document = function(textOrLines) {
|
|||
**/
|
||||
|
||||
// check for IE split bug
|
||||
if ("aaa".split(/a/).length === 0) {
|
||||
if ("aaa".split(/a/).length === 0)
|
||||
this.$split = function(text) {
|
||||
return text.replace(/\r\n|\r/g, "\n").split("\n");
|
||||
};
|
||||
} else {
|
||||
else
|
||||
this.$split = function(text) {
|
||||
return text.split(/\r\n|\r|\n/);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
this.$detectNewLine = function(text) {
|
||||
|
|
@ -208,49 +207,32 @@ var Document = function(textOrLines) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Returns all the text within `range` as a single string.
|
||||
* @param {Range} range The range to work with.
|
||||
* [Given a range within the document, this function returns all the text within that range as a single string.]{: #Document.getTextRange.desc}
|
||||
* @param {Range} range The range to work with
|
||||
*
|
||||
* @returns {String}
|
||||
**/
|
||||
this.getTextRange = function(range) {
|
||||
return this.getLinesForRange(range).join(this.getNewLineCharacter());
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all the text within `range` as an array of lines.
|
||||
* @param {Range} range The range to work with.
|
||||
*
|
||||
* @returns {Array}
|
||||
**/
|
||||
this.getLinesForRange = function(range) {
|
||||
var lines;
|
||||
if (range.start.row === range.end.row) {
|
||||
// Handle a single-line range.
|
||||
lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)];
|
||||
} else {
|
||||
// Handle a multi-line range.
|
||||
lines = this.getLines(range.start.row, range.end.row);
|
||||
lines[0] = (lines[0] || "").substring(range.start.column);
|
||||
var l = lines.length - 1;
|
||||
if (range.end.row - range.start.row == l)
|
||||
lines[l] = lines[l].substring(0, range.end.column);
|
||||
if (range.start.row == range.end.row) {
|
||||
return this.getLine(range.start.row)
|
||||
.substring(range.start.column, range.end.column);
|
||||
}
|
||||
return lines;
|
||||
var lines = this.getLines(range.start.row, range.end.row);
|
||||
lines[0] = (lines[0] || "").substring(range.start.column);
|
||||
var l = lines.length - 1;
|
||||
if (range.end.row - range.start.row == l)
|
||||
lines[l] = lines[l].substring(0, range.end.column);
|
||||
return lines.join(this.getNewLineCharacter());
|
||||
};
|
||||
|
||||
// Deprecated methods retained for backwards compatibility.
|
||||
this.insertLines = function(row, lines) {
|
||||
console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead.");
|
||||
return this.insertFullLines(row, lines);
|
||||
};
|
||||
this.removeLines = function(firstRow, lastRow) {
|
||||
console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead.");
|
||||
return this.removeFullLines(firstRow, lastRow);
|
||||
};
|
||||
this.insertNewLine = function(position) {
|
||||
console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead.");
|
||||
return this.insertMergedLines(position, ["", ""]);
|
||||
this.$clipPosition = function(position) {
|
||||
var length = this.getLength();
|
||||
if (position.row >= length) {
|
||||
position.row = Math.max(0, length - 1);
|
||||
position.column = this.getLine(length-1).length;
|
||||
} else if (position.row < 0)
|
||||
position.row = 0;
|
||||
return position;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -261,160 +243,160 @@ var Document = function(textOrLines) {
|
|||
*
|
||||
**/
|
||||
this.insert = function(position, text) {
|
||||
// Only detect new lines if the document has no line break yet.
|
||||
if (!text || text.length === 0)
|
||||
return position;
|
||||
|
||||
position = this.$clipPosition(position);
|
||||
|
||||
// only detect new lines if the document has no line break yet
|
||||
if (this.getLength() <= 1)
|
||||
this.$detectNewLine(text);
|
||||
|
||||
return this.insertMergedLines(position, this.$split(text));
|
||||
|
||||
var lines = this.$split(text);
|
||||
var firstLine = lines.splice(0, 1)[0];
|
||||
var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];
|
||||
|
||||
position = this.insertInLine(position, firstLine);
|
||||
if (lastLine !== null) {
|
||||
position = this.insertNewLine(position); // terminate first line
|
||||
position = this._insertLines(position.row, lines);
|
||||
position = this.insertInLine(position, lastLine || "");
|
||||
}
|
||||
return position;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Inserts `text` into the `position` at the current row. This method also triggers the `"change"` event.
|
||||
*
|
||||
* This differs from the `insert` method in two ways:
|
||||
* 1. This does NOT handle newline characters (single-line text only).
|
||||
* 2. This is faster than the `insert` method for single-line text insertions.
|
||||
*
|
||||
* Fires whenever the document changes.
|
||||
*
|
||||
* Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available:
|
||||
*
|
||||
* * `"insertLines"` (emitted by [[Document.insertLines]])
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `lines`: the lines in the document that are changing
|
||||
* * `"insertText"` (emitted by [[Document.insertNewLine]])
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `text`: the text that's being added
|
||||
* * `"removeLines"` (emitted by [[Document.insertLines]])
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `lines`: the lines in the document that were removed
|
||||
* * `nl`: the new line character (as defined by [[Document.getNewLineCharacter]])
|
||||
* * `"removeText"` (emitted by [[Document.removeInLine]] and [[Document.removeNewLine]])
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `text`: the text that's being removed
|
||||
*
|
||||
* @event change
|
||||
* @param {Object} e Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties.
|
||||
*
|
||||
**/
|
||||
/**
|
||||
* Inserts the elements in `lines` into the document, starting at the row index given by `row`. This method also triggers the `'change'` event.
|
||||
* @param {Number} row The index of the row to insert at
|
||||
* @param {Array} lines An array of strings
|
||||
* @returns {Object} Contains the final row and column, like this:
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
* If `lines` is empty, this function returns an object containing the current row, and column, like this:
|
||||
* ```
|
||||
* {row: row, column: 0}
|
||||
* ```
|
||||
*
|
||||
**/
|
||||
this.insertLines = function(row, lines) {
|
||||
if (row >= this.getLength())
|
||||
return this.insert({row: row, column: 0}, "\n" + lines.join("\n"));
|
||||
return this._insertLines(Math.max(row, 0), lines);
|
||||
};
|
||||
this._insertLines = function(row, lines) {
|
||||
if (lines.length == 0)
|
||||
return {row: row, column: 0};
|
||||
|
||||
// Apply doesn't work for big arrays due to max call stack detection.
|
||||
// Chrome 64 bit requires threshold smaller than 32k, using a safe value of 20k.
|
||||
// To circumvent that we have to break huge inserts into smaller chunks here.
|
||||
while (lines.length > 20000) {
|
||||
var end = this._insertLines(row, lines.slice(0, 20000));
|
||||
lines = lines.slice(20000);
|
||||
row = end.row;
|
||||
}
|
||||
|
||||
var args = [row, 0];
|
||||
args.push.apply(args, lines);
|
||||
this.$lines.splice.apply(this.$lines, args);
|
||||
|
||||
var range = new Range(row, 0, row + lines.length, 0);
|
||||
var delta = {
|
||||
action: "insertLines",
|
||||
range: range,
|
||||
lines: lines
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
return range.end;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts a new line into the document at the current row's `position`. This method also triggers the `'change'` event.
|
||||
* @param {Object} position The position to insert at
|
||||
* @returns {Object} Returns an object containing the final row and column, like this:<br/>
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
*
|
||||
**/
|
||||
this.insertNewLine = function(position) {
|
||||
position = this.$clipPosition(position);
|
||||
var line = this.$lines[position.row] || "";
|
||||
|
||||
this.$lines[position.row] = line.substring(0, position.column);
|
||||
this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));
|
||||
|
||||
var end = {
|
||||
row : position.row + 1,
|
||||
column : 0
|
||||
};
|
||||
|
||||
var delta = {
|
||||
action: "insertText",
|
||||
range: Range.fromPoints(position, end),
|
||||
text: this.getNewLineCharacter()
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
|
||||
return end;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event.
|
||||
* @param {Object} position The position to insert at; it's an object that looks like `{ row: row, column: column}`
|
||||
* @param {String} text A chunk of text
|
||||
* @returns {Object} Returns an object containing the final row and column, like this:
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
*
|
||||
**/
|
||||
this.insertInLine = function(position, text) {
|
||||
var start = this.clippedPos(position.row, position.column);
|
||||
var end = this.pos(position.row, position.column + text.length);
|
||||
|
||||
this.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "insert",
|
||||
lines: [text]
|
||||
}, true);
|
||||
|
||||
return this.clonePos(end);
|
||||
};
|
||||
|
||||
this.clippedPos = function(row, column) {
|
||||
var length = this.getLength();
|
||||
if (row === undefined) {
|
||||
row = length;
|
||||
} else if (row < 0) {
|
||||
row = 0;
|
||||
} else if (row >= length) {
|
||||
row = length - 1;
|
||||
column = undefined;
|
||||
}
|
||||
var line = this.getLine(row);
|
||||
if (column == undefined)
|
||||
column = line.length;
|
||||
column = Math.min(Math.max(column, 0), line.length);
|
||||
return {row: row, column: column};
|
||||
};
|
||||
|
||||
this.clonePos = function(pos) {
|
||||
return {row: pos.row, column: pos.column};
|
||||
};
|
||||
|
||||
this.pos = function(row, column) {
|
||||
return {row: row, column: column};
|
||||
};
|
||||
|
||||
this.$clipPosition = function(position) {
|
||||
var length = this.getLength();
|
||||
if (position.row >= length) {
|
||||
position.row = Math.max(0, length - 1);
|
||||
position.column = this.getLine(length - 1).length;
|
||||
} else {
|
||||
position.row = Math.max(0, position.row);
|
||||
position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length);
|
||||
}
|
||||
return position;
|
||||
};
|
||||
if (text.length == 0)
|
||||
return position;
|
||||
|
||||
/**
|
||||
* Fires whenever the document changes.
|
||||
*
|
||||
* Several methods trigger different `"change"` events. Below is a list of each action type, followed by each property that's also available:
|
||||
*
|
||||
* * `"insert"`
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `lines`: the lines being added
|
||||
* * `"remove"`
|
||||
* * `range`: the [[Range]] of the change within the document
|
||||
* * `lines`: the lines being removed
|
||||
*
|
||||
* @event change
|
||||
* @param {Object} e Contains at least one property called `"action"`. `"action"` indicates the action that triggered the change. Each action also has a set of additional properties.
|
||||
*
|
||||
**/
|
||||
|
||||
/**
|
||||
* Inserts the elements in `lines` into the document as full lines (does not merge with existing line), starting at the row index given by `row`. This method also triggers the `"change"` event.
|
||||
* @param {Number} row The index of the row to insert at
|
||||
* @param {Array} lines An array of strings
|
||||
* @returns {Object} Contains the final row and column, like this:
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
* If `lines` is empty, this function returns an object containing the current row, and column, like this:
|
||||
* ```
|
||||
* {row: row, column: 0}
|
||||
* ```
|
||||
*
|
||||
**/
|
||||
this.insertFullLines = function(row, lines) {
|
||||
// Clip to document.
|
||||
// Allow one past the document end.
|
||||
row = Math.min(Math.max(row, 0), this.getLength());
|
||||
|
||||
// Calculate insertion point.
|
||||
var column = 0;
|
||||
if (row < this.getLength()) {
|
||||
// Insert before the specified row.
|
||||
lines = lines.concat([""]);
|
||||
column = 0;
|
||||
} else {
|
||||
// Insert after the last row in the document.
|
||||
lines = [""].concat(lines);
|
||||
row--;
|
||||
column = this.$lines[row].length;
|
||||
}
|
||||
|
||||
// Insert.
|
||||
this.insertMergedLines({row: row, column: column}, lines);
|
||||
};
|
||||
var line = this.$lines[position.row] || "";
|
||||
|
||||
this.$lines[position.row] = line.substring(0, position.column) + text
|
||||
+ line.substring(position.column);
|
||||
|
||||
/**
|
||||
* Inserts the elements in `lines` into the document, starting at the position index given by `row`. This method also triggers the `"change"` event.
|
||||
* @param {Number} row The index of the row to insert at
|
||||
* @param {Array} lines An array of strings
|
||||
* @returns {Object} Contains the final row and column, like this:
|
||||
* ```
|
||||
* {row: endRow, column: 0}
|
||||
* ```
|
||||
* If `lines` is empty, this function returns an object containing the current row, and column, like this:
|
||||
* ```
|
||||
* {row: row, column: 0}
|
||||
* ```
|
||||
*
|
||||
**/
|
||||
this.insertMergedLines = function(position, lines) {
|
||||
var start = this.clippedPos(position.row, position.column);
|
||||
var end = {
|
||||
row: start.row + lines.length - 1,
|
||||
column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length
|
||||
row : position.row,
|
||||
column : position.column + text.length
|
||||
};
|
||||
|
||||
this.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "insert",
|
||||
lines: lines
|
||||
});
|
||||
|
||||
return this.clonePos(end);
|
||||
|
||||
var delta = {
|
||||
action: "insertText",
|
||||
range: Range.fromPoints(position, end),
|
||||
text: text
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
|
||||
return end;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -424,90 +406,113 @@ var Document = function(textOrLines) {
|
|||
*
|
||||
**/
|
||||
this.remove = function(range) {
|
||||
var start = this.clippedPos(range.start.row, range.start.column);
|
||||
var end = this.clippedPos(range.end.row, range.end.column);
|
||||
this.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "remove",
|
||||
lines: this.getLinesForRange({start: start, end: end})
|
||||
});
|
||||
return this.clonePos(start);
|
||||
if (!(range instanceof Range))
|
||||
range = Range.fromPoints(range.start, range.end);
|
||||
// clip to document
|
||||
range.start = this.$clipPosition(range.start);
|
||||
range.end = this.$clipPosition(range.end);
|
||||
|
||||
if (range.isEmpty())
|
||||
return range.start;
|
||||
|
||||
var firstRow = range.start.row;
|
||||
var lastRow = range.end.row;
|
||||
|
||||
if (range.isMultiLine()) {
|
||||
var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;
|
||||
var lastFullRow = lastRow - 1;
|
||||
|
||||
if (range.end.column > 0)
|
||||
this.removeInLine(lastRow, 0, range.end.column);
|
||||
|
||||
if (lastFullRow >= firstFullRow)
|
||||
this._removeLines(firstFullRow, lastFullRow);
|
||||
|
||||
if (firstFullRow != firstRow) {
|
||||
this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);
|
||||
this.removeNewLine(range.start.row);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.removeInLine(firstRow, range.start.column, range.end.column);
|
||||
}
|
||||
return range.start;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the specified columns from the `row`. This method also triggers a `"change"` event.
|
||||
* @param {Number} row The row to remove from
|
||||
* @param {Number} startColumn The column to start removing at
|
||||
* @param {Number} endColumn The column to stop removing at
|
||||
* @returns {Object} Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.<br/>If `startColumn` is equal to `endColumn`, this function returns nothing.
|
||||
*
|
||||
**/
|
||||
* Removes the specified columns from the `row`. This method also triggers the `'change'` event.
|
||||
* @param {Number} row The row to remove from
|
||||
* @param {Number} startColumn The column to start removing at
|
||||
* @param {Number} endColumn The column to stop removing at
|
||||
* @returns {Object} Returns an object containing `startRow` and `startColumn`, indicating the new row and column values.<br/>If `startColumn` is equal to `endColumn`, this function returns nothing.
|
||||
*
|
||||
**/
|
||||
this.removeInLine = function(row, startColumn, endColumn) {
|
||||
var start = this.clippedPos(row, startColumn);
|
||||
var end = this.clippedPos(row, endColumn);
|
||||
|
||||
this.applyDelta({
|
||||
start: start,
|
||||
end: end,
|
||||
action: "remove",
|
||||
lines: this.getLinesForRange({start: start, end: end})
|
||||
}, true);
|
||||
|
||||
return this.clonePos(start);
|
||||
if (startColumn == endColumn)
|
||||
return;
|
||||
|
||||
var range = new Range(row, startColumn, row, endColumn);
|
||||
var line = this.getLine(row);
|
||||
var removed = line.substring(startColumn, endColumn);
|
||||
var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);
|
||||
this.$lines.splice(row, 1, newLine);
|
||||
|
||||
var delta = {
|
||||
action: "removeText",
|
||||
range: range,
|
||||
text: removed
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
return range.start;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a range of full lines. This method also triggers the `"change"` event.
|
||||
* Removes a range of full lines. This method also triggers the `'change'` event.
|
||||
* @param {Number} firstRow The first row to be removed
|
||||
* @param {Number} lastRow The last row to be removed
|
||||
* @returns {[String]} Returns all the removed lines.
|
||||
*
|
||||
**/
|
||||
this.removeFullLines = function(firstRow, lastRow) {
|
||||
// Clip to document.
|
||||
firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1);
|
||||
lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1);
|
||||
|
||||
// Calculate deletion range.
|
||||
// Delete the ending new line unless we're at the end of the document.
|
||||
// If we're at the end of the document, delete the starting new line.
|
||||
var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0;
|
||||
var deleteLastNewLine = lastRow < this.getLength() - 1;
|
||||
var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow );
|
||||
var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 );
|
||||
var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow );
|
||||
var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length );
|
||||
var range = new Range(startRow, startCol, endRow, endCol);
|
||||
|
||||
// Store delelted lines with bounding newlines ommitted (maintains previous behavior).
|
||||
var deletedLines = this.$lines.slice(firstRow, lastRow + 1);
|
||||
|
||||
this.applyDelta({
|
||||
start: range.start,
|
||||
end: range.end,
|
||||
action: "remove",
|
||||
lines: this.getLinesForRange(range)
|
||||
});
|
||||
|
||||
// Return the deleted lines.
|
||||
return deletedLines;
|
||||
this.removeLines = function(firstRow, lastRow) {
|
||||
if (firstRow < 0 || lastRow >= this.getLength())
|
||||
return this.remove(new Range(firstRow, 0, lastRow + 1, 0));
|
||||
return this._removeLines(firstRow, lastRow);
|
||||
};
|
||||
|
||||
this._removeLines = function(firstRow, lastRow) {
|
||||
var range = new Range(firstRow, 0, lastRow + 1, 0);
|
||||
var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);
|
||||
|
||||
var delta = {
|
||||
action: "removeLines",
|
||||
range: range,
|
||||
nl: this.getNewLineCharacter(),
|
||||
lines: removed
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
return removed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the new line between `row` and the row immediately following it. This method also triggers the `"change"` event.
|
||||
* Removes the new line between `row` and the row immediately following it. This method also triggers the `'change'` event.
|
||||
* @param {Number} row The row to check
|
||||
*
|
||||
**/
|
||||
this.removeNewLine = function(row) {
|
||||
if (row < this.getLength() - 1 && row >= 0) {
|
||||
this.applyDelta({
|
||||
start: this.pos(row, this.getLine(row).length),
|
||||
end: this.pos(row + 1, 0),
|
||||
action: "remove",
|
||||
lines: ["", ""]
|
||||
});
|
||||
}
|
||||
var firstLine = this.getLine(row);
|
||||
var secondLine = this.getLine(row+1);
|
||||
|
||||
var range = new Range(row, firstLine.length, row+1, 0);
|
||||
var line = firstLine + secondLine;
|
||||
|
||||
this.$lines.splice(row, 2, line);
|
||||
|
||||
var delta = {
|
||||
action: "removeText",
|
||||
range: range,
|
||||
text: this.getNewLineCharacter()
|
||||
};
|
||||
this._signal("change", { data: delta });
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -521,9 +526,9 @@ var Document = function(textOrLines) {
|
|||
*
|
||||
**/
|
||||
this.replace = function(range, text) {
|
||||
if (!range instanceof Range)
|
||||
if (!(range instanceof Range))
|
||||
range = Range.fromPoints(range.start, range.end);
|
||||
if (text.length === 0 && range.isEmpty())
|
||||
if (text.length == 0 && range.isEmpty())
|
||||
return range.start;
|
||||
|
||||
// Shortcut: If the text we want to insert is the same as it is already
|
||||
|
|
@ -532,106 +537,55 @@ var Document = function(textOrLines) {
|
|||
return range.end;
|
||||
|
||||
this.remove(range);
|
||||
var end;
|
||||
if (text) {
|
||||
end = this.insert(range.start, text);
|
||||
var end = this.insert(range.start, text);
|
||||
}
|
||||
else {
|
||||
end = range.start;
|
||||
}
|
||||
|
||||
|
||||
return end;
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies all changes in `deltas` to the document.
|
||||
* @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions)
|
||||
* Applies all the changes previously accumulated. These can be either `'insertText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
||||
**/
|
||||
this.applyDeltas = function(deltas) {
|
||||
for (var i=0; i<deltas.length; i++) {
|
||||
this.applyDelta(deltas[i]);
|
||||
var delta = deltas[i];
|
||||
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||
|
||||
if (delta.action == "insertLines")
|
||||
this.insertLines(range.start.row, delta.lines);
|
||||
else if (delta.action == "insertText")
|
||||
this.insert(range.start, delta.text);
|
||||
else if (delta.action == "removeLines")
|
||||
this._removeLines(range.start.row, range.end.row - 1);
|
||||
else if (delta.action == "removeText")
|
||||
this.remove(range);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reverts all changes in `deltas` from the document.
|
||||
* @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions)
|
||||
* Reverts any changes previously applied. These can be either `'insertText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`.
|
||||
**/
|
||||
this.revertDeltas = function(deltas) {
|
||||
for (var i=deltas.length-1; i>=0; i--) {
|
||||
this.revertDelta(deltas[i]);
|
||||
var delta = deltas[i];
|
||||
|
||||
var range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||
|
||||
if (delta.action == "insertLines")
|
||||
this._removeLines(range.start.row, range.end.row - 1);
|
||||
else if (delta.action == "insertText")
|
||||
this.remove(range);
|
||||
else if (delta.action == "removeLines")
|
||||
this._insertLines(range.start.row, delta.lines);
|
||||
else if (delta.action == "removeText")
|
||||
this.insert(range.start, delta.text);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies `delta` to the document.
|
||||
* @param {Object} delta A delta object (can include "insert" and "remove" actions)
|
||||
**/
|
||||
this.applyDelta = function(delta, doNotValidate) {
|
||||
var isInsert = delta.action == "insert";
|
||||
// An empty range is a NOOP.
|
||||
if (isInsert ? delta.lines.length <= 1 && !delta.lines[0]
|
||||
: !Range.comparePoints(delta.start, delta.end)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInsert && delta.lines.length > 20000)
|
||||
this.$splitAndapplyLargeDelta(delta, 20000);
|
||||
|
||||
// Apply.
|
||||
applyDelta(this.$lines, delta, doNotValidate);
|
||||
this._signal("change", delta);
|
||||
};
|
||||
|
||||
this.$splitAndapplyLargeDelta = function(delta, MAX) {
|
||||
// Split large insert deltas. This is necessary because:
|
||||
// 1. We need to support splicing delta lines into the document via $lines.splice.apply(...)
|
||||
// 2. fn.apply() doesn't work for a large number of params. The smallest threshold is on chrome 40 ~42000.
|
||||
// we use 20000 to leave some space for actual stack
|
||||
//
|
||||
// To Do: Ideally we'd be consistent and also split 'delete' deltas. We don't do this now, because delete
|
||||
// delta handling is too slow. If we make delete delta handling faster we can split all large deltas
|
||||
// as shown in https://gist.github.com/aldendaniels/8367109#file-document-snippet-js
|
||||
// If we do this, update validateDelta() to limit the number of lines in a delete delta.
|
||||
var lines = delta.lines;
|
||||
var l = lines.length;
|
||||
var row = delta.start.row;
|
||||
var column = delta.start.column;
|
||||
var from = 0, to = 0;
|
||||
do {
|
||||
from = to;
|
||||
to += MAX - 1;
|
||||
var chunk = lines.slice(from, to);
|
||||
if (to > l) {
|
||||
// Update remaining delta.
|
||||
delta.lines = chunk;
|
||||
delta.start.row = row + from;
|
||||
delta.start.column = column;
|
||||
break;
|
||||
}
|
||||
chunk.push("");
|
||||
this.applyDelta({
|
||||
start: this.pos(row + from, column),
|
||||
end: this.pos(row + to, column = 0),
|
||||
action: delta.action,
|
||||
lines: chunk
|
||||
}, true);
|
||||
} while(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts `delta` from the document.
|
||||
* @param {Object} delta A delta object (can include "insert" and "remove" actions)
|
||||
**/
|
||||
this.revertDelta = function(delta) {
|
||||
this.applyDelta({
|
||||
start: this.clonePos(delta.start),
|
||||
end: this.clonePos(delta.end),
|
||||
action: (delta.action == "insert" ? "remove" : "insert"),
|
||||
lines: delta.lines.slice()
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts an index position in a document to a `{row, column}` object.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insert({row: 0, column: 1}, "juhu");
|
||||
assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n"));
|
||||
|
|
@ -63,9 +63,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insertMergedLines({row: 0, column: 1}, ['', '']);
|
||||
doc.insertNewLine({row: 0, column: 1});
|
||||
assert.equal(doc.getValue(), ["1", "2", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
|
|
@ -80,9 +80,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insertFullLines(0, ["aa", "bb"]);
|
||||
doc.insertLines(0, ["aa", "bb"]);
|
||||
assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
|
|
@ -97,9 +97,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insertFullLines(2, ["aa", "bb"]);
|
||||
doc.insertLines(2, ["aa", "bb"]);
|
||||
assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n"));
|
||||
},
|
||||
|
||||
|
|
@ -107,9 +107,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insertFullLines(1, ["aa", "bb"]);
|
||||
doc.insertLines(1, ["aa", "bb"]);
|
||||
assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
|
|
@ -124,7 +124,7 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insert({row: 0, column: 0}, "aa\nbb\ncc");
|
||||
assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n"));
|
||||
|
|
@ -141,9 +141,9 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insert({row: 1, column: 2}, "aa\nbb\ncc");
|
||||
doc.insert({row: 2, column: 0}, "aa\nbb\ncc");
|
||||
assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n"));
|
||||
|
||||
var d = deltas.concat();
|
||||
|
|
@ -158,7 +158,7 @@ module.exports = {
|
|||
var doc = new Document(["12", "34"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.insert({row: 0, column: 1}, "aa\nbb\ncc");
|
||||
assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n"));
|
||||
|
|
@ -175,7 +175,7 @@ module.exports = {
|
|||
var doc = new Document(["1234", "5678"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.remove(new Range(0, 1, 0, 3));
|
||||
assert.equal(doc.getValue(), ["14", "5678"].join("\n"));
|
||||
|
|
@ -192,7 +192,7 @@ module.exports = {
|
|||
var doc = new Document(["1234", "5678"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.remove(new Range(0, 4, 1, 0));
|
||||
assert.equal(doc.getValue(), ["12345678"].join("\n"));
|
||||
|
|
@ -209,7 +209,7 @@ module.exports = {
|
|||
var doc = new Document(["1234", "5678", "abcd"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.remove(new Range(0, 2, 2, 2));
|
||||
assert.equal(doc.getValue(), ["12cd"].join("\n"));
|
||||
|
|
@ -226,7 +226,7 @@ module.exports = {
|
|||
var doc = new Document(["1234", "5678", "abcd"]);
|
||||
|
||||
var deltas = [];
|
||||
doc.on("change", function(e) { deltas.push(e); });
|
||||
doc.on("change", function(e) { deltas.push(e.data); });
|
||||
|
||||
doc.remove(new Range(1, 0, 3, 0));
|
||||
assert.equal(doc.getValue(), ["1234", ""].join("\n"));
|
||||
|
|
@ -235,7 +235,7 @@ module.exports = {
|
|||
"test: remove lines should return the removed lines" : function() {
|
||||
var doc = new Document(["1234", "5678", "abcd"]);
|
||||
|
||||
var removed = doc.removeFullLines(1, 2);
|
||||
var removed = doc.removeLines(1, 2);
|
||||
assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n"));
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ var EditSession = function(text, mode) {
|
|||
this.$foldData = [];
|
||||
this.$foldData.toString = function() {
|
||||
return this.join("\n");
|
||||
};
|
||||
}
|
||||
this.on("changeFold", this.onChangeFold.bind(this));
|
||||
this.$onChange = this.onChange.bind(this);
|
||||
|
||||
|
|
@ -249,12 +249,13 @@ var EditSession = function(text, mode) {
|
|||
this.$resetRowCache(fold.start.row);
|
||||
};
|
||||
|
||||
this.onChange = function(delta) {
|
||||
this.onChange = function(e) {
|
||||
var delta = e.data;
|
||||
this.$modified = true;
|
||||
|
||||
this.$resetRowCache(delta.start.row);
|
||||
this.$resetRowCache(delta.range.start.row);
|
||||
|
||||
var removedFolds = this.$updateInternalDataOnChange(delta);
|
||||
var removedFolds = this.$updateInternalDataOnChange(e);
|
||||
if (!this.$fromUndo && this.$undoManager && !delta.ignore) {
|
||||
this.$deltasDoc.push(delta);
|
||||
if (removedFolds && removedFolds.length != 0) {
|
||||
|
|
@ -268,7 +269,7 @@ var EditSession = function(text, mode) {
|
|||
}
|
||||
|
||||
this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta);
|
||||
this._signal("change", delta);
|
||||
this._signal("change", e);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -678,10 +679,10 @@ var EditSession = function(text, mode) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Returns an object containing all of the markers, either front or back.
|
||||
* Returns an array containing the IDs of all the markers, either front or back.
|
||||
* @param {Boolean} inFront If `true`, indicates you only want front markers; `false` indicates only back markers
|
||||
*
|
||||
* @returns {Object}
|
||||
* @returns {Array}
|
||||
**/
|
||||
this.getMarkers = function(inFront) {
|
||||
return inFront ? this.$frontMarkers : this.$backMarkers;
|
||||
|
|
@ -1145,19 +1146,6 @@ var EditSession = function(text, mode) {
|
|||
this.remove = function(range) {
|
||||
return this.doc.remove(range);
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a range of full lines. This method also triggers the `'change'` event.
|
||||
* @param {Number} firstRow The first row to be removed
|
||||
* @param {Number} lastRow The last row to be removed
|
||||
* @returns {[String]} Returns all the removed lines.
|
||||
*
|
||||
* @related Document.removeFullLines
|
||||
*
|
||||
**/
|
||||
this.removeFullLines = function(firstRow, lastRow){
|
||||
return this.doc.removeFullLines(firstRow, lastRow);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts previous changes to your document.
|
||||
|
|
@ -1234,36 +1222,39 @@ var EditSession = function(text, mode) {
|
|||
|
||||
this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {
|
||||
function isInsert(delta) {
|
||||
return isUndo ? delta.action !== "insert" : delta.action === "insert";
|
||||
var insert =
|
||||
delta.action === "insertText" || delta.action === "insertLines";
|
||||
return isUndo ? !insert : insert;
|
||||
}
|
||||
|
||||
var delta = deltas[0];
|
||||
var range, point;
|
||||
var lastDeltaIsInsert = false;
|
||||
if (isInsert(delta)) {
|
||||
range = Range.fromPoints(delta.start, delta.end);
|
||||
range = Range.fromPoints(delta.range.start, delta.range.end);
|
||||
lastDeltaIsInsert = true;
|
||||
} else {
|
||||
range = Range.fromPoints(delta.start, delta.start);
|
||||
range = Range.fromPoints(delta.range.start, delta.range.start);
|
||||
lastDeltaIsInsert = false;
|
||||
}
|
||||
|
||||
for (var i = 1; i < deltas.length; i++) {
|
||||
delta = deltas[i];
|
||||
if (isInsert(delta)) {
|
||||
point = delta.start;
|
||||
point = delta.range.start;
|
||||
if (range.compare(point.row, point.column) == -1) {
|
||||
range.setStart(point);
|
||||
range.setStart(delta.range.start);
|
||||
}
|
||||
point = delta.end;
|
||||
point = delta.range.end;
|
||||
if (range.compare(point.row, point.column) == 1) {
|
||||
range.setEnd(point);
|
||||
range.setEnd(delta.range.end);
|
||||
}
|
||||
lastDeltaIsInsert = true;
|
||||
} else {
|
||||
point = delta.start;
|
||||
point = delta.range.start;
|
||||
if (range.compare(point.row, point.column) == -1) {
|
||||
range = Range.fromPoints(delta.start, delta.start);
|
||||
range =
|
||||
Range.fromPoints(delta.range.start, delta.range.start);
|
||||
}
|
||||
lastDeltaIsInsert = false;
|
||||
}
|
||||
|
|
@ -1377,7 +1368,7 @@ var EditSession = function(text, mode) {
|
|||
this.indentRows = function(startRow, endRow, indentString) {
|
||||
indentString = indentString.replace(/\t/g, this.getTabString());
|
||||
for (var row=startRow; row<=endRow; row++)
|
||||
this.doc.insertInLine({row: row, column: 0}, indentString);
|
||||
this.insert({row: row, column:0}, indentString);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1434,11 +1425,11 @@ var EditSession = function(text, mode) {
|
|||
x.end.row += diff;
|
||||
return x;
|
||||
});
|
||||
|
||||
|
||||
var lines = dir == 0
|
||||
? this.doc.getLines(firstRow, lastRow)
|
||||
: this.doc.removeFullLines(firstRow, lastRow);
|
||||
this.doc.insertFullLines(firstRow+diff, lines);
|
||||
: this.doc.removeLines(firstRow, lastRow);
|
||||
this.doc.insertLines(firstRow+diff, lines);
|
||||
folds.length && this.addFolds(folds);
|
||||
return diff;
|
||||
};
|
||||
|
|
@ -1448,6 +1439,8 @@ var EditSession = function(text, mode) {
|
|||
* @param {Number} lastRow The final row to move up
|
||||
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
|
||||
*
|
||||
* @related Document.insertLines
|
||||
*
|
||||
**/
|
||||
this.moveLinesUp = function(firstRow, lastRow) {
|
||||
return this.$moveLines(firstRow, lastRow, -1);
|
||||
|
|
@ -1458,6 +1451,8 @@ var EditSession = function(text, mode) {
|
|||
* @param {Number} firstRow The starting row to move down
|
||||
* @param {Number} lastRow The final row to move down
|
||||
* @returns {Number} If `firstRow` is less-than or equal to 0, this function returns 0. Otherwise, on success, it returns -1.
|
||||
*
|
||||
* @related Document.insertLines
|
||||
**/
|
||||
this.moveLinesDown = function(firstRow, lastRow) {
|
||||
return this.$moveLines(firstRow, lastRow, 1);
|
||||
|
|
@ -1661,23 +1656,34 @@ var EditSession = function(text, mode) {
|
|||
};
|
||||
};
|
||||
|
||||
this.$updateInternalDataOnChange = function(delta) {
|
||||
this.$updateInternalDataOnChange = function(e) {
|
||||
var useWrapMode = this.$useWrapMode;
|
||||
var action = delta.action;
|
||||
var start = delta.start;
|
||||
var end = delta.end;
|
||||
var firstRow = start.row;
|
||||
var lastRow = end.row;
|
||||
var len = lastRow - firstRow;
|
||||
var len;
|
||||
var action = e.data.action;
|
||||
var firstRow = e.data.range.start.row;
|
||||
var lastRow = e.data.range.end.row;
|
||||
var start = e.data.range.start;
|
||||
var end = e.data.range.end;
|
||||
var removedFolds = null;
|
||||
|
||||
|
||||
if (action.indexOf("Lines") != -1) {
|
||||
if (action == "insertLines") {
|
||||
lastRow = firstRow + (e.data.lines.length);
|
||||
} else {
|
||||
lastRow = firstRow;
|
||||
}
|
||||
len = e.data.lines ? e.data.lines.length : lastRow - firstRow;
|
||||
} else {
|
||||
len = lastRow - firstRow;
|
||||
}
|
||||
|
||||
this.$updating = true;
|
||||
if (len != 0) {
|
||||
if (action === "remove") {
|
||||
if (action.indexOf("remove") != -1) {
|
||||
this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len);
|
||||
|
||||
var foldLines = this.$foldData;
|
||||
removedFolds = this.getFoldsInRange(delta);
|
||||
removedFolds = this.getFoldsInRange(e.data.range);
|
||||
this.removeFolds(removedFolds);
|
||||
|
||||
var foldLine = this.getFoldLine(end.row);
|
||||
|
|
@ -1742,10 +1748,10 @@ var EditSession = function(text, mode) {
|
|||
} else {
|
||||
// Realign folds. E.g. if you add some new chars before a fold, the
|
||||
// fold should "move" to the right.
|
||||
len = Math.abs(delta.start.column - delta.end.column);
|
||||
if (action === "remove") {
|
||||
len = Math.abs(e.data.range.start.column - e.data.range.end.column);
|
||||
if (action.indexOf("remove") != -1) {
|
||||
// Get all the folds in the change range and remove them.
|
||||
removedFolds = this.getFoldsInRange(delta);
|
||||
removedFolds = this.getFoldsInRange(e.data.range);
|
||||
this.removeFolds(removedFolds);
|
||||
|
||||
len = -len;
|
||||
|
|
|
|||
|
|
@ -829,13 +829,15 @@ function Folding() {
|
|||
}
|
||||
};
|
||||
|
||||
this.updateFoldWidgets = function(delta) {
|
||||
var firstRow = delta.start.row;
|
||||
var len = delta.end.row - firstRow;
|
||||
this.updateFoldWidgets = function(e) {
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
var firstRow = range.start.row;
|
||||
var len = range.end.row - firstRow;
|
||||
|
||||
if (len === 0) {
|
||||
this.foldWidgets[firstRow] = null;
|
||||
} else if (delta.action == 'remove') {
|
||||
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
||||
this.foldWidgets.splice(firstRow, len + 1, null);
|
||||
} else {
|
||||
var args = Array(len + 1);
|
||||
|
|
|
|||
|
|
@ -442,12 +442,12 @@ module.exports = {
|
|||
session.setTabSize(4);
|
||||
assert.equal(session.getScreenWidth(), 2);
|
||||
|
||||
session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']);
|
||||
session.doc.insertFullLines(1, ["123"]);
|
||||
session.doc.insertNewLine({row: 0, column: Infinity});
|
||||
session.doc.insertLines(1, ["123"]);
|
||||
assert.equal(session.getScreenWidth(), 3);
|
||||
|
||||
session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']);
|
||||
session.doc.insertFullLines(1, ["\t\t"]);
|
||||
session.doc.insertNewLine({row: 0, column: Infinity});
|
||||
session.doc.insertLines(1, ["\t\t"]);
|
||||
|
||||
assert.equal(session.getScreenWidth(), 8);
|
||||
|
||||
|
|
@ -471,9 +471,9 @@ module.exports = {
|
|||
|
||||
session.setUseWrapMode(true);
|
||||
|
||||
document.insertFullLines(0, ["a", "b"]);
|
||||
document.insertFullLines(2, ["c", "d"]);
|
||||
document.removeFullLines(1, 2);
|
||||
document.insertLines(0, ["a", "b"]);
|
||||
document.insertLines(2, ["c", "d"]);
|
||||
document.removeLines(1, 2);
|
||||
},
|
||||
|
||||
"test wrapMode init has to create wrapData array": function() {
|
||||
|
|
|
|||
|
|
@ -692,15 +692,20 @@ var Editor = function(renderer, session) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.onDocumentChange = function(delta) {
|
||||
// Rerender and emit "change" event.
|
||||
var wrap = this.session.$useWrapMode;
|
||||
var lastRow = (delta.start.row == delta.end.row ? delta.end.row : Infinity);
|
||||
this.renderer.updateLines(delta.start.row, lastRow, wrap);
|
||||
this.onDocumentChange = function(e) {
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
var lastRow;
|
||||
|
||||
this._signal("change", delta);
|
||||
|
||||
// Update cursor because tab characters can influence the cursor position.
|
||||
if (range.start.row == range.end.row && delta.action != "insertLines" && delta.action != "removeLines")
|
||||
lastRow = range.end.row;
|
||||
else
|
||||
lastRow = Infinity;
|
||||
this.renderer.updateLines(range.start.row, lastRow, this.session.$useWrapMode);
|
||||
|
||||
this._signal("change", e);
|
||||
|
||||
// update cursor because tab characters can influence the cursor position
|
||||
this.$cursorChange();
|
||||
this.$updateHighlightActiveLine();
|
||||
};
|
||||
|
|
@ -915,16 +920,14 @@ var Editor = function(renderer, session) {
|
|||
*
|
||||
*
|
||||
**/
|
||||
this.onPaste = function(text, event) {
|
||||
var e = {text: text, event: event};
|
||||
this.commands.exec("paste", this, e);
|
||||
};
|
||||
|
||||
this.$handlePaste = function(e) {
|
||||
if (typeof e == "string")
|
||||
e = {text: e};
|
||||
this.onPaste = function(text) {
|
||||
// todo this should change when paste becomes a command
|
||||
if (this.$readOnly)
|
||||
return;
|
||||
|
||||
var e = {text: text};
|
||||
this._signal("paste", e);
|
||||
var text = e.text;
|
||||
text = e.text;
|
||||
if (!this.inMultiSelectMode || this.inVirtualSelectionMode) {
|
||||
this.insert(text);
|
||||
} else {
|
||||
|
|
@ -942,6 +945,7 @@ var Editor = function(renderer, session) {
|
|||
this.session.insert(range.start, lines[i]);
|
||||
}
|
||||
}
|
||||
this.renderer.scrollCursorIntoView();
|
||||
};
|
||||
|
||||
this.execCommand = function(command, args) {
|
||||
|
|
@ -1629,7 +1633,15 @@ var Editor = function(renderer, session) {
|
|||
**/
|
||||
this.removeLines = function() {
|
||||
var rows = this.$getSelectedRows();
|
||||
this.session.removeFullLines(rows.first, rows.last);
|
||||
var range;
|
||||
if (rows.first === 0 || rows.last+1 < this.session.getLength())
|
||||
range = new Range(rows.first, 0, rows.last+1, 0);
|
||||
else
|
||||
range = new Range(
|
||||
rows.first-1, this.session.getLine(rows.first-1).length,
|
||||
rows.last, this.session.getLine(rows.last).length
|
||||
);
|
||||
this.session.remove(range);
|
||||
this.clearSelection();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -578,14 +578,15 @@ var onSelectionChange = function(evt) {
|
|||
* and deleting text.
|
||||
* @param {!Event} evt The event.
|
||||
*/
|
||||
var onChange = function(delta) {
|
||||
var onChange = function(evt) {
|
||||
var data = evt.data;
|
||||
switch (data.action) {
|
||||
case 'remove':
|
||||
case 'removeText':
|
||||
cvox.Api.speak(data.text, 0, DELETED_PROP);
|
||||
/* Let the future cursor change event know it's from text change. */
|
||||
changed = true;
|
||||
break;
|
||||
case 'insert':
|
||||
case 'insertText':
|
||||
cvox.Api.speak(data.text, 0);
|
||||
/* Let the future cursor change event know it's from text change. */
|
||||
changed = true;
|
||||
|
|
|
|||
|
|
@ -44,12 +44,13 @@ var ElasticTabstopsLite = function(editor) {
|
|||
this.onExec = function() {
|
||||
recordChanges = true;
|
||||
};
|
||||
this.onChange = function(delta) {
|
||||
this.onChange = function(e) {
|
||||
var range = e.data.range
|
||||
if (recordChanges) {
|
||||
if (changedRows.indexOf(delta.start.row) == -1)
|
||||
changedRows.push(delta.start.row);
|
||||
if (delta.end.row != delta.start.row)
|
||||
changedRows.push(delta.end.row);
|
||||
if (changedRows.indexOf(range.start.row) == -1)
|
||||
changedRows.push(range.start.row);
|
||||
if (range.end.row != range.start.row)
|
||||
changedRows.push(range.end.row);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -117,13 +117,12 @@ var supportedModes = {
|
|||
MUSHCode: ["mc|mush"],
|
||||
MySQL: ["mysql"],
|
||||
Nix: ["nix"],
|
||||
Nim: ["nim"],
|
||||
ObjectiveC: ["m|mm"],
|
||||
OCaml: ["ml|mli"],
|
||||
Pascal: ["pas|p"],
|
||||
Perl: ["pl|pm"],
|
||||
pgSQL: ["pgsql"],
|
||||
PHP: ["php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp"],
|
||||
PHP: ["php|phtml"],
|
||||
Powershell: ["ps1"],
|
||||
Praat: ["praat|praatscript|psc|proc"],
|
||||
Prolog: ["plg|prolog"],
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ var baseStyles = require("../requirejs/text!./static.css");
|
|||
var config = require("../config");
|
||||
var dom = require("../lib/dom");
|
||||
|
||||
var SimpleTextLayer = function() {
|
||||
this.config = {};
|
||||
};
|
||||
SimpleTextLayer.prototype = TextLayer.prototype;
|
||||
|
||||
var highlight = function(el, opts, callback) {
|
||||
var m = el.className.match(/lang-(\w+)/);
|
||||
|
|
@ -153,8 +149,12 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) {
|
|||
session.setUseWorker(false);
|
||||
session.setMode(mode);
|
||||
|
||||
var textLayer = new SimpleTextLayer();
|
||||
var textLayer = new TextLayer(document.createElement("div"));
|
||||
textLayer.setSession(session);
|
||||
textLayer.config = {
|
||||
characterWidth: 10,
|
||||
lineHeight: 20
|
||||
};
|
||||
|
||||
session.setValue(input);
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ var themeData = [
|
|||
["Solarized Dark" ,"solarized_dark" , "dark"],
|
||||
["Terminal" ,"terminal" , "dark"],
|
||||
["Tomorrow Night" ,"tomorrow_night" , "dark"],
|
||||
["The Night After Tomorrow" ,"the_night_after_tomorrow" , "dark"],
|
||||
["Tomorrow Night Blue" ,"tomorrow_night_blue" , "dark"],
|
||||
["Tomorrow Night Bright","tomorrow_night_bright" , "dark"],
|
||||
["Tomorrow Night 80s" ,"tomorrow_night_eighties" , "dark"],
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ var TextInput = function(parentNode, host) {
|
|||
var data = handleClipboardData(e);
|
||||
if (typeof data == "string") {
|
||||
if (data)
|
||||
host.onPaste(data, e);
|
||||
host.onPaste(data);
|
||||
if (useragent.isIE)
|
||||
setTimeout(resetSelection);
|
||||
event.preventDefault(e);
|
||||
|
|
|
|||
|
|
@ -178,6 +178,13 @@ define(function(require, exports, module) {
|
|||
return this.ace.inVirtualSelectionMode && this.ace.selection.index;
|
||||
};
|
||||
this.onChange = function(delta) {
|
||||
var oldDelta = delta.data;
|
||||
delta = {
|
||||
start: oldDelta.range.start,
|
||||
end: oldDelta.range.end,
|
||||
action: oldDelta.action,
|
||||
lines: oldDelta.lines || [oldDelta.text]
|
||||
};// v1.2 api compatibility
|
||||
if (delta.action[0] == 'i') {
|
||||
var change = { text: delta.lines };
|
||||
var curOp = this.curOp = this.curOp || {};
|
||||
|
|
@ -571,6 +578,7 @@ define(function(require, exports, module) {
|
|||
highlight.session = null;
|
||||
};
|
||||
highlight.updateOnChange = function(delta) {
|
||||
delta = delta.data.range;// v1.2 api compatibility
|
||||
var row = delta.start.row;
|
||||
if (row == delta.end.row) highlight.cache[row] = undefined;
|
||||
else highlight.cache.splice(row, highlight.cache.length);
|
||||
|
|
|
|||
|
|
@ -100,14 +100,16 @@ var Gutter = function(parentEl) {
|
|||
}
|
||||
};
|
||||
|
||||
this.$updateAnnotations = function (delta) {
|
||||
this.$updateAnnotations = function (e) {
|
||||
if (!this.$annotations.length)
|
||||
return;
|
||||
var firstRow = delta.start.row;
|
||||
var len = delta.end.row - firstRow;
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
var firstRow = range.start.row;
|
||||
var len = range.end.row - firstRow;
|
||||
if (len === 0) {
|
||||
// do nothing
|
||||
} else if (delta.action == 'remove') {
|
||||
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
||||
this.$annotations.splice(firstRow, len + 1, null);
|
||||
} else {
|
||||
var args = new Array(len + 1);
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ var Marker = function(parentEl) {
|
|||
else
|
||||
this.drawMultiLineMarker(html, range, marker.clazz, config);
|
||||
} else {
|
||||
this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config);
|
||||
this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config);
|
||||
}
|
||||
}
|
||||
this.element.innerHTML = html.join("");
|
||||
|
|
@ -100,30 +100,29 @@ var Marker = function(parentEl) {
|
|||
return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
|
||||
};
|
||||
|
||||
function getBorderClass(tl, tr, br, bl) {
|
||||
return (tl ? 1 : 0) | (tr ? 2 : 0) | (br ? 4 : 0) | (bl ? 8 : 0);
|
||||
}
|
||||
// Draws a marker, which spans a range of text on multiple lines
|
||||
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) {
|
||||
// selection start
|
||||
var row = range.start.row;
|
||||
var session = this.session;
|
||||
var start = range.start.row;
|
||||
var end = range.end.row;
|
||||
var row = start;
|
||||
var prev = 0;
|
||||
var curr = 0;
|
||||
var next = session.getScreenLastRowColumn(row);
|
||||
var lineRange = new Range(row, range.start.column, row, curr);
|
||||
for (; row <= end; row++) {
|
||||
lineRange.start.row = lineRange.end.row = row;
|
||||
lineRange.start.column = row == start ? range.start.column : session.getRowWrapIndent(row);
|
||||
lineRange.end.column = next;
|
||||
prev = curr;
|
||||
curr = next;
|
||||
next = row + 1 < end ? session.getScreenLastRowColumn(row + 1) : row == end ? 0 : range.end.column;
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange,
|
||||
clazz + (row == start ? " ace_start" : "") + " ace_br"
|
||||
+ getBorderClass(row == start || row == start + 1 && range.start.column, prev < curr, curr > next, row == end),
|
||||
layerConfig, row == end ? 0 : 1, extraStyle);
|
||||
|
||||
var lineRange = new Range(
|
||||
row, range.start.column,
|
||||
row, session.getScreenLastRowColumn(row)
|
||||
);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " ace_start", layerConfig, 1, extraStyle);
|
||||
|
||||
// selection end
|
||||
row = range.end.row;
|
||||
lineRange = new Range(row, session.getRowWrapIndent(row), row, range.end.column);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle);
|
||||
|
||||
for (row = range.start.row + 1; row < range.end.row; row++) {
|
||||
lineRange.start.row = row;
|
||||
lineRange.start.column = session.getRowWrapIndent(row);
|
||||
lineRange.end.row = row;
|
||||
lineRange.end.column = session.getScreenLastRowColumn(row);
|
||||
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -137,7 +136,7 @@ var Marker = function(parentEl) {
|
|||
extraStyle = extraStyle || "";
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, " ace_br1 ace_start' style='",
|
||||
"<div class='", clazz, " ace_start' style='",
|
||||
"height:", height, "px;",
|
||||
"right:0;",
|
||||
"top:", top, "px;",
|
||||
|
|
@ -149,7 +148,7 @@ var Marker = function(parentEl) {
|
|||
var width = range.end.column * config.characterWidth;
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, " ace_br12' style='",
|
||||
"<div class='", clazz, "' style='",
|
||||
"height:", height, "px;",
|
||||
"width:", width, "px;",
|
||||
"top:", top, "px;",
|
||||
|
|
@ -161,11 +160,9 @@ var Marker = function(parentEl) {
|
|||
if (height <= 0)
|
||||
return;
|
||||
top = this.$getTop(range.start.row + 1, config);
|
||||
|
||||
var radiusClass = (range.start.column ? 1 : 0) | (range.end.column ? 0 : 8);
|
||||
|
||||
stringBuilder.push(
|
||||
"<div class='", clazz, (radiusClass ? " ace_br" + radiusClass : ""), "' style='",
|
||||
"<div class='", clazz, "' style='",
|
||||
"height:", height, "px;",
|
||||
"right:0;",
|
||||
"top:", top, "px;",
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ var Text = function(parentEl) {
|
|||
this.EOL_CHAR_LF = "\xAC";
|
||||
this.EOL_CHAR_CRLF = "\xa4";
|
||||
this.EOL_CHAR = this.EOL_CHAR_LF;
|
||||
this.TAB_CHAR = "\u2014"; //"\u21E5";
|
||||
this.TAB_CHAR = "\u2192"; //"\u21E5";
|
||||
this.SPACE_CHAR = "\xB7";
|
||||
this.$padding = 0;
|
||||
|
||||
|
|
@ -128,7 +128,8 @@ var Text = function(parentEl) {
|
|||
for (var i = 1; i < tabSize + 1; i++) {
|
||||
if (this.showInvisibles) {
|
||||
tabStr.push("<span class='ace_invisible ace_invisible_tab'>"
|
||||
+ lang.stringRepeat(this.TAB_CHAR, i)
|
||||
+ this.TAB_CHAR
|
||||
+ lang.stringRepeat(" ", i - 1)
|
||||
+ "</span>");
|
||||
} else {
|
||||
tabStr.push(lang.stringRepeat(" ", i));
|
||||
|
|
@ -144,7 +145,7 @@ var Text = function(parentEl) {
|
|||
spaceClass = " ace_invisible_space";
|
||||
tabClass = " ace_invisible_tab";
|
||||
var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize);
|
||||
var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize);
|
||||
var tabContent = this.TAB_CHAR + lang.stringRepeat(" ", this.tabSize - 1);
|
||||
} else{
|
||||
var spaceContent = lang.stringRepeat(" ", this.tabSize);
|
||||
var tabContent = spaceContent;
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ module.exports = {
|
|||
var EOL = "<span class='ace_invisible ace_invisible_eol'>" + textLayer.EOL_CHAR + "</span>";
|
||||
var SPACE = function(i) {return Array(i+1).join(" ")}
|
||||
var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR)}
|
||||
var TAB = function(i) {return Array(i+1).join(textLayer.TAB_CHAR)}
|
||||
var TAB = function(i) {return textLayer.TAB_CHAR + SPACE(i-1)}
|
||||
function testRender(results) {
|
||||
for (var i = results.length; i--; ) {
|
||||
var stringBuilder = [];
|
||||
|
|
|
|||
|
|
@ -91,11 +91,6 @@ exports.toggleCssClass = function(el, name) {
|
|||
return add;
|
||||
};
|
||||
|
||||
if (typeof document == "undefined") {
|
||||
exports.importCssString = function() {};
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add or remove a CSS class from the list of classes on the given node
|
||||
* depending on the value of <tt>include</tt>
|
||||
|
|
@ -178,6 +173,9 @@ exports.getInnerHeight = function(element) {
|
|||
};
|
||||
|
||||
|
||||
if (typeof document == "undefined")
|
||||
return;
|
||||
|
||||
if (window.pageYOffset !== undefined) {
|
||||
exports.getPageScrollTop = function() {
|
||||
return window.pageYOffset;
|
||||
|
|
|
|||
|
|
@ -113,16 +113,18 @@ function LineWidgets(session) {
|
|||
});
|
||||
};
|
||||
|
||||
this.updateOnChange = function(delta) {
|
||||
this.updateOnChange = function(e) {
|
||||
var lineWidgets = this.session.lineWidgets;
|
||||
if (!lineWidgets) return;
|
||||
|
||||
var startRow = delta.start.row;
|
||||
var len = delta.end.row - startRow;
|
||||
|
||||
var delta = e.data;
|
||||
var range = delta.range;
|
||||
var startRow = range.start.row;
|
||||
var len = range.end.row - startRow;
|
||||
|
||||
if (len === 0) {
|
||||
// return
|
||||
} else if (delta.action == 'remove') {
|
||||
} else if (delta.action == "removeText" || delta.action == "removeLines") {
|
||||
var removed = lineWidgets.splice(startRow + 1, len);
|
||||
removed.forEach(function(w) {
|
||||
w && this.removeLineWidget(w);
|
||||
|
|
|
|||
|
|
@ -56,34 +56,34 @@
|
|||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
["comment","|"],
|
||||
["string"," start "],
|
||||
["comment","|"],
|
||||
["string"," eat "],
|
||||
["comment","|"],
|
||||
["string"," left "],
|
||||
["comment","| "],
|
||||
["string","start "],
|
||||
["comment","| "],
|
||||
["string","eat "],
|
||||
["comment","| "],
|
||||
["string","left "],
|
||||
["comment","|"]
|
||||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
["comment","|"],
|
||||
["string"," 12 "],
|
||||
["comment","|"],
|
||||
["string"," 5 "],
|
||||
["comment","|"],
|
||||
["string"," 7 "],
|
||||
["comment","| "],
|
||||
["string"," 12 "],
|
||||
["comment","| "],
|
||||
["string"," 5 "],
|
||||
["comment","| "],
|
||||
["string"," 7 "],
|
||||
["comment","|"]
|
||||
],[
|
||||
"start",
|
||||
["text"," "],
|
||||
["comment","|"],
|
||||
["string"," 20 "],
|
||||
["comment","|"],
|
||||
["string"," 5 "],
|
||||
["comment","|"],
|
||||
["string"," 15 "],
|
||||
["comment","|"],
|
||||
["string"," "]
|
||||
["comment","| "],
|
||||
["string"," 20 "],
|
||||
["comment","| "],
|
||||
["string"," 5 "],
|
||||
["comment","| "],
|
||||
["string"," 15 "],
|
||||
["comment","| "],
|
||||
["string"," "]
|
||||
],[
|
||||
"start"
|
||||
],[
|
||||
|
|
|
|||
|
|
@ -144,16 +144,6 @@ module.exports = {
|
|||
exec("selectleft", 1);
|
||||
exec("insertstring", 1, '"');
|
||||
assert.equal(editor.getValue(), '("foo")');
|
||||
|
||||
editor.setValue("", 1);
|
||||
exec("selectleft", 1);
|
||||
exec("insertstring", 1, '"');
|
||||
assert.equal(editor.getValue(), '""');
|
||||
exec("insertstring", 1, '\\');
|
||||
exec("insertstring", 1, 'n');
|
||||
exec("insertstring", 1, '"');
|
||||
assert.equal(editor.getValue(), '"\\n"');
|
||||
|
||||
},
|
||||
"test: xml": function() {
|
||||
editor = new Editor(new MockRenderer());
|
||||
|
|
|
|||
|
|
@ -269,8 +269,8 @@ var CstyleBehaviour = function() {
|
|||
if (leftChar == "\\" && token && /escape/.test(token.type))
|
||||
return null;
|
||||
|
||||
var stringBefore = token && /string|escape/.test(token.type);
|
||||
var stringAfter = !rightToken || /string|escape/.test(rightToken.type);
|
||||
var stringBefore = token && /string/.test(token.type);
|
||||
var stringAfter = !rightToken || /string/.test(rightToken.type);
|
||||
|
||||
var pair;
|
||||
if (rightChar == quote) {
|
||||
|
|
|
|||
|
|
@ -36,18 +36,18 @@ var stringEscape = "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]
|
|||
|
||||
var GherkinHighlightRules = function() {
|
||||
|
||||
// need to include constant ints
|
||||
// need to include constant ints
|
||||
this.$rules = {
|
||||
start : [{
|
||||
start : [{
|
||||
token: 'constant.numeric',
|
||||
regex: "(?:(?:[1-9]\\d*)|(?:0))"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
token : "keyword",
|
||||
regex : "Feature:|Background:|Scenario:|Scenario\ Outline:|Examples:|Given|When|Then|And|But|\\*",
|
||||
}, {
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
token : "keyword",
|
||||
regex : "Feature:|Background:|Scenario:|Scenario\ Outline:|Examples:|Given|When|Then|And|But|\\*",
|
||||
}, {
|
||||
token : "string", // multi line """ string start
|
||||
regex : '"{3}',
|
||||
next : "qqstring3"
|
||||
|
|
@ -56,22 +56,22 @@ var GherkinHighlightRules = function() {
|
|||
regex : '"',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "@[A-Za-z0-9]+",
|
||||
next : "start"
|
||||
token : "comment",
|
||||
regex : "@[A-Za-z0-9]+",
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "<.+>"
|
||||
token : "comment",
|
||||
regex : "<.+>"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "\\|(?=.)",
|
||||
next : "table-item"
|
||||
token : "comment",
|
||||
regex : "\\| ",
|
||||
next : "table-item"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : "\\|$",
|
||||
next : "start"
|
||||
token : "comment",
|
||||
regex : "\\|$",
|
||||
next : "start"
|
||||
}],
|
||||
"qqstring3" : [ {
|
||||
"qqstring3" : [ {
|
||||
token : "constant.language.escape",
|
||||
regex : stringEscape
|
||||
}, {
|
||||
|
|
@ -81,7 +81,7 @@ var GherkinHighlightRules = function() {
|
|||
}, {
|
||||
defaultToken : "string"
|
||||
}],
|
||||
"qqstring" : [{
|
||||
"qqstring" : [{
|
||||
token : "constant.language.escape",
|
||||
regex : stringEscape
|
||||
}, {
|
||||
|
|
@ -96,19 +96,15 @@ var GherkinHighlightRules = function() {
|
|||
defaultToken: "string"
|
||||
}],
|
||||
"table-item" : [{
|
||||
token : "comment",
|
||||
regex : /$/,
|
||||
next : "start"
|
||||
}, {
|
||||
token : "comment",
|
||||
regex : /\|/
|
||||
}, {
|
||||
token : "string",
|
||||
regex : /\\./
|
||||
}, {
|
||||
defaultToken : "string"
|
||||
}]
|
||||
regex : "[A-Za-z0-9 ]*",
|
||||
next : "start"
|
||||
}],
|
||||
};
|
||||
|
||||
|
||||
//new TextHighlightRules().getRules();
|
||||
|
||||
}
|
||||
|
||||
oop.inherits(GherkinHighlightRules, TextHighlightRules);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ var Mode = function() {
|
|||
HtmlMode.call(this);
|
||||
this.HighlightRules = HandlebarsHighlightRules;
|
||||
this.$behaviour = new HtmlBehaviour();
|
||||
|
||||
|
||||
this.foldingRules = new HtmlFoldMode();
|
||||
};
|
||||
|
|
@ -20,7 +21,7 @@ var Mode = function() {
|
|||
oop.inherits(Mode, HtmlMode);
|
||||
|
||||
(function() {
|
||||
this.blockComment = {start: "{{!--", end: "--}}"};
|
||||
this.blockComment = {start: "{!--", end: "--}"};
|
||||
this.$id = "ace/mode/handlebars";
|
||||
}).call(Mode.prototype);
|
||||
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ var LessHighlightRules = function() {
|
|||
regex: "\\.[a-z0-9-_]+"
|
||||
}, {
|
||||
token: "variable.language",
|
||||
regex: ":[a-z_][a-z0-9-_]*"
|
||||
regex: ":[a-z0-9-_]+"
|
||||
}, {
|
||||
token: "constant",
|
||||
regex: "[a-z0-9-_]+"
|
||||
|
|
|
|||
|
|
@ -1,113 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2010, Ajax.org B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ajax.org B.V. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextMode = require("./text").Mode;
|
||||
var NimHighlightRules = require("./nim_highlight_rules").NimHighlightRules;
|
||||
var NimFoldMode = require("./folding/pythonic").FoldMode;
|
||||
var Range = require("../range").Range;
|
||||
|
||||
var Mode = function() {
|
||||
this.HighlightRules = NimHighlightRules;
|
||||
this.foldingRules = new NimFoldMode("\\:|=");
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.lineCommentStart = "#";
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
var indent = this.$getIndent(line);
|
||||
|
||||
var tokenizedLine = this.getTokenizer().getLineTokens(line, state);
|
||||
var tokens = tokenizedLine.tokens;
|
||||
|
||||
if (tokens.length && tokens[tokens.length-1].type == "comment") {
|
||||
return indent;
|
||||
}
|
||||
|
||||
if (state == "start") {
|
||||
var match = line.match(/^.*[\{\(\[\:=]\s*$/);
|
||||
if (match) {
|
||||
indent += tab;
|
||||
}
|
||||
}
|
||||
|
||||
return indent;
|
||||
};
|
||||
|
||||
var outdents = {
|
||||
"discard": 1,
|
||||
"return": 1,
|
||||
"raise": 1,
|
||||
"break": 1,
|
||||
"continue": 1
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
if (input !== "\r\n" && input !== "\r" && input !== "\n")
|
||||
return false;
|
||||
|
||||
var tokens = this.getTokenizer().getLineTokens(line.trim(), state).tokens;
|
||||
|
||||
if (!tokens)
|
||||
return false;
|
||||
|
||||
// ignore trailing comments
|
||||
do {
|
||||
var last = tokens.pop();
|
||||
} while (last && (last.type == "comment" || (last.type == "text" && last.value.match(/^\s+$/))));
|
||||
|
||||
if (!last)
|
||||
return false;
|
||||
|
||||
return (last.type == "keyword" && outdents[last.value]);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
// outdenting in python is slightly different because it always applies
|
||||
// to the next line and only of a new line is inserted
|
||||
|
||||
row += 1;
|
||||
var indent = this.$getIndent(doc.getLine(row));
|
||||
var tab = doc.getTabString();
|
||||
if (indent.slice(-tab.length) == tab)
|
||||
doc.remove(new Range(row, indent.length-tab.length, row, indent.length));
|
||||
};
|
||||
|
||||
this.$id = "ace/mode/nim";
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
});
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2010, Ajax.org B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ajax.org B.V. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
/*
|
||||
* TODO: nim delimiters
|
||||
*/
|
||||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("../lib/oop");
|
||||
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
||||
var num_suffix = "(\'[Ff]32|\'[Ff]64|\'[IiUu]8|\'[IiUu]16|\'[IiUu]32|\'[IiUu]64)";
|
||||
|
||||
var NimHighlightRules = function() {
|
||||
|
||||
var keywords = (
|
||||
"addr|and|as|asm|atomic|bind|block|break|case|cast|const|continue|" +
|
||||
"converter|defer|discard|distinct|div|do|elif|else|end|enum|except|" +
|
||||
"export|finally|for|from|func|generic|if|import|in|include|interface|" +
|
||||
"is|isnot|iterator|let|macro|method|mixin|mod|nil|not|notin|object|of|" +
|
||||
"or|out|proc|ptr|raise|ref|return|shl|shr|static|template|try|tuple|" +
|
||||
"type|using|var|when|while|with|without|xor|yield"
|
||||
);
|
||||
|
||||
var builtinConstants = (
|
||||
"true|false|nil|NotImplemented|Ellipsis"
|
||||
);
|
||||
|
||||
var storageType = (
|
||||
"string|seq|array|expr|stmt|typed|untyped|any|auto|bool|cdouble|cfloat|"+
|
||||
"cchar|clongdouble|clong|clonglong|cshort|csize|cstring|cstringarray|"+
|
||||
"culong|culonglong|cushort|guarded|natural|openarray|ordinal|pointer|"+
|
||||
"range|set|shared|static|typedesc|varargs|void"
|
||||
);
|
||||
|
||||
var builtinFunctions = (
|
||||
"defined|declared|declaredInScope|echo|$"
|
||||
);
|
||||
|
||||
//var futureReserved = "";
|
||||
var keywordMapper = this.createKeywordMapper({
|
||||
"invalid.deprecated": "debugger",
|
||||
"support.function": builtinFunctions,
|
||||
//"invalid.illegal": futureReserved,
|
||||
"constant.language": builtinConstants,
|
||||
"storage.type" : storageType,
|
||||
"keyword": keywords
|
||||
}, "identifier");
|
||||
|
||||
var strPre = "(?:r|R)?";
|
||||
|
||||
var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
|
||||
var octInteger = "(?:0[o]?[0-7]+)";
|
||||
var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
|
||||
var binInteger = "(?:0[bB][01]+)";
|
||||
var integer = "(?:" + decimalInteger + "|" + octInteger + "|" + hexInteger + "|" + binInteger + ")";
|
||||
|
||||
var exponent = "(?:[eE][+-]?\\d+)";
|
||||
var fraction = "(?:\\.\\d+)";
|
||||
var intPart = "(?:\\d+)";
|
||||
var pointFloat = "(?:(?:" + intPart + "?" + fraction + ")|(?:" + intPart + "\\.))";
|
||||
var exponentFloat = "(?:(?:" + pointFloat + "|" + intPart + ")" + exponent + ")";
|
||||
var floatNumber = "(?:" + exponentFloat + "|" + pointFloat + ")";
|
||||
|
||||
var stringEscape = "\\\\(x[0-9A-Fa-f]{2}|[0-7]{3}|[\\\\abfnrtv'\"]|U[0-9A-Fa-f]{8}|u[0-9A-Fa-f]{4})";
|
||||
|
||||
this.$rules = {
|
||||
"start" : [ {
|
||||
token : "comment",
|
||||
regex : "#.*$"
|
||||
}, {
|
||||
token : "keyword",
|
||||
regex : "(proc|method|temdplate|macro|macromethod|converter|func|iterator) ",
|
||||
next : "qproc_name"
|
||||
}, {
|
||||
token : "storage.type",
|
||||
regex : "(c|cu|u)?int(8|16|32|64)?",
|
||||
}, {
|
||||
token : "storage.type",
|
||||
regex : "(c|cu|u|cs)?char",
|
||||
}, {
|
||||
token : "storage.type",
|
||||
regex : "float(32|64)?",
|
||||
}, {
|
||||
token : "docstring",
|
||||
regex : "##.*$"
|
||||
}, {
|
||||
token : "string", // multi line """ string start
|
||||
regex : strPre + '"{3}',
|
||||
next : "qqstring3"
|
||||
}, {
|
||||
token : "string", // " string
|
||||
regex : strPre + '"(?=.)',
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string", // multi line ''' string start
|
||||
regex : strPre + "'{3}",
|
||||
next : "qstring3"
|
||||
}, {
|
||||
token : "backtick", // ` string
|
||||
regex : strPre + "`(?=.)",
|
||||
next : "qxstring"
|
||||
}, {
|
||||
token : "string", // ' string
|
||||
regex : strPre + "'(?=.)",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "constant.numeric", // imaginary
|
||||
regex : "(?:" + floatNumber + "|\\d+)[jJ]\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // float
|
||||
regex : floatNumber
|
||||
}, {
|
||||
token : "constant.numeric", // long integer
|
||||
regex : integer + "[lL]\\b"
|
||||
}, {
|
||||
token : "constant.numeric", // integer
|
||||
regex : integer + "\\b"
|
||||
}, {
|
||||
token : keywordMapper,
|
||||
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\+|\\-|\\*|\\*\\*|\\/|\\/\\/|%|<<|>>|&|\\||\\^|~|<|>|<=|=>|==|!=|<>|="
|
||||
}, {
|
||||
token : "paren.lparen",
|
||||
regex : "[\\[\\(\\{]"
|
||||
}, {
|
||||
token : "paren.rparen",
|
||||
regex : "[\\]\\)\\}]"
|
||||
}, {
|
||||
token : "text",
|
||||
regex : "\\s+"
|
||||
} ],
|
||||
"qqstring3" : [ {
|
||||
token : "constant.language.escape",
|
||||
regex : stringEscape
|
||||
}, {
|
||||
token : "string", // multi line """ string end
|
||||
regex : '"{3}',
|
||||
next : "start"
|
||||
}, {
|
||||
defaultToken : "string"
|
||||
} ],
|
||||
"qstring3" : [ {
|
||||
token : "constant.language.escape",
|
||||
regex : stringEscape
|
||||
}, {
|
||||
token : "string", // multi line ''' string end
|
||||
regex : "'{3}",
|
||||
next : "start"
|
||||
}, {
|
||||
defaultToken : "string"
|
||||
} ],
|
||||
"qqstring" : [{
|
||||
token : "constant.language.escape",
|
||||
regex : stringEscape
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "\\\\$",
|
||||
next : "qqstring"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : '"|$',
|
||||
next : "start"
|
||||
}, {
|
||||
defaultToken: "string"
|
||||
}],
|
||||
"qstring" : [{
|
||||
token : "constant.language.escape",
|
||||
regex : stringEscape
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "\\\\$",
|
||||
next : "qstring"
|
||||
}, {
|
||||
token : "string",
|
||||
regex : "'|$",
|
||||
next : "start"
|
||||
}, {
|
||||
defaultToken: "string"
|
||||
}],
|
||||
"qxstring" : [{
|
||||
token : "constant.language.escape",
|
||||
regex : stringEscape
|
||||
}, {
|
||||
token : "backtick",
|
||||
regex : "\\\\$",
|
||||
next : "qxstring"
|
||||
}, {
|
||||
token : "backtick",
|
||||
regex : "`|$",
|
||||
next : "start"
|
||||
}, {
|
||||
defaultToken: "backtick"
|
||||
}],
|
||||
"qproc_name":[{
|
||||
token : "proc_name",
|
||||
regex : "\\w+",
|
||||
},{
|
||||
token : "start_bracket",
|
||||
regex : "(\\(|=|$)",
|
||||
next : "start"
|
||||
}],
|
||||
};
|
||||
};
|
||||
|
||||
oop.inherits(NimHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.NimHighlightRules = NimHighlightRules;
|
||||
});
|
||||
|
|
@ -39,92 +39,15 @@ define(function(require, exports, module) {
|
|||
var oop = require("../lib/oop");
|
||||
var TextMode = require("./text").Mode;
|
||||
var SchemeHighlightRules = require("./scheme_highlight_rules").SchemeHighlightRules;
|
||||
var MatchingParensOutdent = require("./matching_parens_outdent").MatchingParensOutdent;
|
||||
|
||||
var Mode = function() {
|
||||
this.HighlightRules = SchemeHighlightRules;
|
||||
this.$outdent = new MatchingParensOutdent();
|
||||
};
|
||||
oop.inherits(Mode, TextMode);
|
||||
|
||||
(function() {
|
||||
|
||||
this.lineCommentStart = ";";
|
||||
this.minorIndentFunctions = ["define", "lambda", "define-macro", "define-syntax", "syntax-rules", "define-record-type", "define-structure"];
|
||||
|
||||
this.$toIndent = function(str) {
|
||||
return str.split('').map(function(ch) {
|
||||
if (/\s/.exec(ch)) {
|
||||
return ch;
|
||||
} else {
|
||||
return ' ';
|
||||
}
|
||||
}).join('');
|
||||
};
|
||||
|
||||
this.$calculateIndent = function(line, tab) {
|
||||
var baseIndent = this.$getIndent(line);
|
||||
var delta = 0;
|
||||
var isParen, ch;
|
||||
// Walk back from end of line, find matching braces
|
||||
for (var i = line.length - 1; i >= 0; i--) {
|
||||
ch = line[i];
|
||||
if (ch === '(') {
|
||||
delta--;
|
||||
isParen = true;
|
||||
} else if (ch === '(' || ch === '[' || ch === '{') {
|
||||
delta--;
|
||||
isParen = false;
|
||||
} else if (ch === ')' || ch === ']' || ch === '}') {
|
||||
delta++;
|
||||
}
|
||||
if (delta < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (delta < 0 && isParen) {
|
||||
// Were more brackets opened than closed and was a ( left open?
|
||||
i += 1;
|
||||
var iBefore = i;
|
||||
var fn = '';
|
||||
while (true) {
|
||||
ch = line[i];
|
||||
if (ch === ' ' || ch === '\t') {
|
||||
if(this.minorIndentFunctions.indexOf(fn) !== -1) {
|
||||
return this.$toIndent(line.substring(0, iBefore - 1) + tab);
|
||||
} else {
|
||||
return this.$toIndent(line.substring(0, i + 1));
|
||||
}
|
||||
} else if (ch === undefined) {
|
||||
return this.$toIndent(line.substring(0, iBefore - 1) + tab);
|
||||
}
|
||||
fn += line[i];
|
||||
i++;
|
||||
}
|
||||
} else if(delta < 0 && !isParen) {
|
||||
// Were more brackets openend than closed and was it not a (?
|
||||
return this.$toIndent(line.substring(0, i+1));
|
||||
} else if(delta > 0) {
|
||||
// Mere more brackets closed than opened? Outdent.
|
||||
baseIndent = baseIndent.substring(0, baseIndent.length - tab.length);
|
||||
return baseIndent;
|
||||
} else {
|
||||
// Were they nicely matched? Just indent like line before.
|
||||
return baseIndent;
|
||||
}
|
||||
};
|
||||
|
||||
this.getNextLineIndent = function(state, line, tab) {
|
||||
return this.$calculateIndent(line, tab);
|
||||
};
|
||||
|
||||
this.checkOutdent = function(state, line, input) {
|
||||
return this.$outdent.checkOutdent(line, input);
|
||||
};
|
||||
|
||||
this.autoOutdent = function(state, doc, row) {
|
||||
this.$outdent.autoOutdent(doc, row);
|
||||
};
|
||||
|
||||
this.$id = "ace/mode/scheme";
|
||||
}).call(Mode.prototype);
|
||||
|
|
|
|||
|
|
@ -57,10 +57,6 @@ var TomlHighlightRules = function() {
|
|||
regex : '"(?=.)',
|
||||
next : "qqstring"
|
||||
},
|
||||
{
|
||||
token: ["variable.keygroup.toml"],
|
||||
regex: "(?:^\\s*)(\\[\\[([^\\]]+)\\]\\])"
|
||||
},
|
||||
{
|
||||
token: ["variable.keygroup.toml"],
|
||||
regex: "(?:^\\s*)(\\[([^\\]]+)\\])"
|
||||
|
|
@ -104,4 +100,4 @@ var TomlHighlightRules = function() {
|
|||
oop.inherits(TomlHighlightRules, TextHighlightRules);
|
||||
|
||||
exports.TomlHighlightRules = TomlHighlightRules;
|
||||
});
|
||||
});
|
||||
|
|
@ -83,7 +83,7 @@ function onMouseDown(e) {
|
|||
var selectionMode;
|
||||
if (editor.$mouseHandler.$enableJumpToDef) {
|
||||
if (ctrl && alt || accel && alt)
|
||||
selectionMode = shift ? "block" : "add";
|
||||
selectionMode = "add";
|
||||
else if (alt && editor.$blockSelectEnabled)
|
||||
selectionMode = "block";
|
||||
} else {
|
||||
|
|
@ -117,7 +117,7 @@ function onMouseDown(e) {
|
|||
|
||||
if (shift) {
|
||||
oldRange = null;
|
||||
range = selection.ranges[0] || range;
|
||||
range = selection.ranges[0];
|
||||
editor.removeSelectionMarker(range);
|
||||
}
|
||||
editor.once("mouseup", function() {
|
||||
|
|
|
|||
|
|
@ -754,9 +754,9 @@ var Editor = require("./editor").Editor;
|
|||
if (fr < 0) fr = 0;
|
||||
if (lr >= max) lr = max - 1;
|
||||
}
|
||||
var lines = this.session.removeFullLines(fr, lr);
|
||||
var lines = this.session.doc.removeLines(fr, lr);
|
||||
lines = this.$reAlignText(lines, guessRange);
|
||||
this.session.insert({row: fr, column: 0}, lines.join("\n") + "\n");
|
||||
this.session.doc.insert({row: fr, column: 0}, lines.join("\n") + "\n");
|
||||
if (!guessRange) {
|
||||
range.start.column = 0;
|
||||
range.end.column = lines[lines.length - 1].length;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
if (typeof process !== "undefined") {
|
||||
require("amd-loader");
|
||||
require("./test/mockdom");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
|
@ -42,7 +41,6 @@ var Range = require("./range").Range;
|
|||
var Editor = require("./editor").Editor;
|
||||
var EditSession = require("./edit_session").EditSession;
|
||||
var MockRenderer = require("./test/mockrenderer").MockRenderer;
|
||||
var UndoManager = require("./undomanager").UndoManager;
|
||||
|
||||
var editor;
|
||||
var exec = function(name, times, args) {
|
||||
|
|
@ -261,20 +259,6 @@ module.exports = {
|
|||
selection.fromJSON(after);
|
||||
assert.ok(!selection.isEqual(before));
|
||||
assert.ok(selection.isEqual(after));
|
||||
},
|
||||
|
||||
"test multiselect align": function() {
|
||||
var doc = new EditSession(["l1", "l2", "l3"]);
|
||||
doc.setUndoManager(new UndoManager());
|
||||
editor = new Editor(new MockRenderer(), doc);
|
||||
var selection = editor.selection;
|
||||
selection.addRange(new Range(1,0,1,0))
|
||||
selection.addRange(new Range(2,2,2,2))
|
||||
editor.execCommand("alignCursors");
|
||||
assert.equal(' l1\n l2\nl3', editor.getValue());
|
||||
doc.markUndoGroup();
|
||||
editor.execCommand("undo");
|
||||
assert.equal('l1\nl2\nl3', editor.getValue());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -150,27 +150,28 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
|
|||
* Emitted when the place holder updates.
|
||||
*
|
||||
**/
|
||||
this.onUpdate = function(delta) {
|
||||
var range = delta;
|
||||
this.onUpdate = function(event) {
|
||||
var delta = event.data;
|
||||
var range = delta.range;
|
||||
if(range.start.row !== range.end.row) return;
|
||||
if(range.start.row !== this.pos.row) return;
|
||||
if (this.$updating) return;
|
||||
this.$updating = true;
|
||||
var lengthDiff = delta.action === "insert" ? range.end.column - range.start.column : range.start.column - range.end.column;
|
||||
var lengthDiff = delta.action === "insertText" ? range.end.column - range.start.column : range.start.column - range.end.column;
|
||||
|
||||
if(range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1) {
|
||||
var distanceFromStart = range.start.column - this.pos.column;
|
||||
this.length += lengthDiff;
|
||||
if(!this.session.$fromUndo) {
|
||||
if(delta.action === 'insert') {
|
||||
if(delta.action === "insertText") {
|
||||
for (var i = this.others.length - 1; i >= 0; i--) {
|
||||
var otherPos = this.others[i];
|
||||
var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
|
||||
if(otherPos.row === range.start.row && range.start.column < otherPos.column)
|
||||
newPos.column += lengthDiff;
|
||||
this.doc.insertMergedLines(newPos, delta.lines);
|
||||
this.doc.insert(newPos, delta.text);
|
||||
}
|
||||
} else if(delta.action === 'remove') {
|
||||
} else if(delta.action === "removeText") {
|
||||
for (var i = this.others.length - 1; i >= 0; i--) {
|
||||
var otherPos = this.others[i];
|
||||
var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};
|
||||
|
|
@ -180,7 +181,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
|
|||
}
|
||||
}
|
||||
// Special case: insert in beginning
|
||||
if(range.start.column === this.pos.column && delta.action === 'insert') {
|
||||
if(range.start.column === this.pos.column && delta.action === "insertText") {
|
||||
setTimeout(function() {
|
||||
this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff);
|
||||
for (var i = 0; i < this.others.length; i++) {
|
||||
|
|
@ -192,7 +193,7 @@ var PlaceHolder = function(session, length, pos, others, mainClass, othersClass)
|
|||
}
|
||||
}.bind(this), 0);
|
||||
}
|
||||
else if(range.start.column === this.pos.column && delta.action === 'remove') {
|
||||
else if(range.start.column === this.pos.column && delta.action === "removeText") {
|
||||
setTimeout(function() {
|
||||
for (var i = 0; i < this.others.length; i++) {
|
||||
var other = this.others[i];
|
||||
|
|
|
|||
|
|
@ -180,13 +180,14 @@ var RangeList = function() {
|
|||
this.session = null;
|
||||
};
|
||||
|
||||
this.$onChange = function(delta) {
|
||||
if (delta.action == "insert"){
|
||||
var start = delta.start;
|
||||
var end = delta.end;
|
||||
this.$onChange = function(e) {
|
||||
var changeRange = e.data.range;
|
||||
if (e.data.action[0] == "i"){
|
||||
var start = changeRange.start;
|
||||
var end = changeRange.end;
|
||||
} else {
|
||||
var end = delta.start;
|
||||
var start = delta.end;
|
||||
var end = changeRange.start;
|
||||
var start = changeRange.end;
|
||||
}
|
||||
var startRow = start.row;
|
||||
var endRow = end.row;
|
||||
|
|
|
|||
|
|
@ -667,11 +667,11 @@ var TabstopManager = function(editor) {
|
|||
this.editor = null;
|
||||
};
|
||||
|
||||
this.onChange = function(delta) {
|
||||
var changeRange = delta;
|
||||
var isRemove = delta.action[0] == "r";
|
||||
var start = delta.start;
|
||||
var end = delta.end;
|
||||
this.onChange = function(e) {
|
||||
var changeRange = e.data.range;
|
||||
var isRemove = e.data.action[0] == "r";
|
||||
var start = changeRange.start;
|
||||
var end = changeRange.end;
|
||||
var startRow = start.row;
|
||||
var endRow = end.row;
|
||||
var lineDif = endRow - startRow;
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
exports.snippetText = require("../requirejs/text!./mask.snippets");
|
||||
exports.scope = "mask";
|
||||
|
||||
});
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
exports.snippetText = require("../requirejs/text!./nim.snippets");
|
||||
exports.scope = "nim";
|
||||
|
||||
});
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
snippet #!
|
||||
#!/usr/bin/env nim
|
||||
snippet imp
|
||||
import ${1:module}
|
||||
snippet from
|
||||
from ${1:package} import ${2:module}
|
||||
# Module Docstring
|
||||
snippet docs
|
||||
## File: ${1:FILENAME:file_name}
|
||||
## Author: ${2:author}
|
||||
## Description: ${3}
|
||||
snippet wh
|
||||
while ${1:condition}:
|
||||
${2:# TODO: write code...}
|
||||
# dowh - does the same as do...while in other languages
|
||||
snippet dowh
|
||||
while true:
|
||||
${1:# TODO: write code...}
|
||||
if ${2:condition}:
|
||||
break
|
||||
snippet with
|
||||
with ${1:expr} as ${2:var}:
|
||||
${3:# TODO: write code...}
|
||||
# New Function
|
||||
snippet proc
|
||||
proc ${1:fname}(${2:`indent('.') ? 'self' : ''`}): ${3: return type} =
|
||||
##${4:docstring for $1}
|
||||
${5:# TODO: write code...}
|
||||
snippet deff
|
||||
def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):
|
||||
${3:# TODO: write code...}
|
||||
# New Method
|
||||
snippet defs
|
||||
def ${1:mname}(self, ${2:arg}):
|
||||
${3:# TODO: write code...}
|
||||
# New Property
|
||||
snippet property
|
||||
def ${1:foo}():
|
||||
doc = "${2:The $1 property.}"
|
||||
def fget(self):
|
||||
${3:return self._$1}
|
||||
def fset(self, value):
|
||||
${4:self._$1 = value}
|
||||
# Ifs
|
||||
snippet if
|
||||
if ${1:condition}:
|
||||
${2:# TODO: write code...}
|
||||
snippet el
|
||||
else:
|
||||
${1:# TODO: write code...}
|
||||
snippet ei
|
||||
elif ${1:condition}:
|
||||
${2:# TODO: write code...}
|
||||
# For
|
||||
snippet for
|
||||
for ${1:item} in ${2:items}:
|
||||
${3:# TODO: write code...}
|
||||
# Encodes
|
||||
snippet cutf8
|
||||
# -*- coding: utf-8 -*-
|
||||
snippet clatin1
|
||||
# -*- coding: latin-1 -*-
|
||||
snippet cascii
|
||||
# -*- coding: ascii -*-
|
||||
# Lambda
|
||||
snippet ld
|
||||
${1:var} = lambda ${2:vars} : ${3:action}
|
||||
snippet .
|
||||
self.
|
||||
snippet try Try/Except
|
||||
try:
|
||||
${1:# TODO: write code...}
|
||||
except ${2:Exception}, ${3:e}:
|
||||
${4:raise $3}
|
||||
snippet try Try/Except/Else
|
||||
try:
|
||||
${1:# TODO: write code...}
|
||||
except ${2:Exception}, ${3:e}:
|
||||
${4:raise $3}
|
||||
else:
|
||||
${5:# TODO: write code...}
|
||||
snippet try Try/Except/Finally
|
||||
try:
|
||||
${1:# TODO: write code...}
|
||||
except ${2:Exception}, ${3:e}:
|
||||
${4:raise $3}
|
||||
finally:
|
||||
${5:# TODO: write code...}
|
||||
snippet try Try/Except/Else/Finally
|
||||
try:
|
||||
${1:# TODO: write code...}
|
||||
except ${2:Exception}, ${3:e}:
|
||||
${4:raise $3}
|
||||
else:
|
||||
${5:# TODO: write code...}
|
||||
finally:
|
||||
${6:# TODO: write code...}
|
||||
# if __name__ == '__main__':
|
||||
snippet ifmain
|
||||
if isMainModule:
|
||||
${1:main()}
|
||||
snippet "
|
||||
## ${1:doc}
|
||||
# test function/method
|
||||
snippet test
|
||||
def test_${1:description}(${2:self}):
|
||||
${3:# TODO: write code...}
|
||||
# test case
|
||||
snippet testcase
|
||||
class ${1:ExampleCase}(unittest.TestCase):
|
||||
|
||||
def test_${2:description}(self):
|
||||
${3:# TODO: write code...}
|
||||
#getopt
|
||||
snippet getopt
|
||||
try:
|
||||
# Short option syntax: "hv:"
|
||||
# Long option syntax: "help" or "verbose="
|
||||
opts, args = getopt.getopt(sys.argv[1:], "${1:short_options}", [${2:long_options}])
|
||||
|
||||
except getopt.GetoptError, err:
|
||||
# Print debug info
|
||||
print str(err)
|
||||
${3:error_action}
|
||||
|
||||
for option, argument in opts:
|
||||
if option in ("-h", "--help"):
|
||||
${4}
|
||||
elif option in ("-v", "--verbose"):
|
||||
verbose = argument
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-clouds.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #FFFFFF;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-clouds .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-clouds-midnight.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #191919;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-clouds-midnight .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-cobalt.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #002240;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-cobalt .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-dawn.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #F9F9F9;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-dawn .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-idle-fingers.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #323232;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-idle-fingers .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
.ace-katzenmilch.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #f3f2f3;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-katzenmilch .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-kr-theme.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #0B0A09;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-kr-theme .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-merbivore.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #161616;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-merbivore .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-merbivore-soft.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #1C1C1C;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-merbivore-soft .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-mono-industrial.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #222C28;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-mono-industrial .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-monokai.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #272822;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-monokai .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-pastel-on-dark.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #2C2828;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-pastel-on-dark .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
.ace-solarized-dark.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #002B36;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-solarized-dark .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-solarized-light.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #FDF6E3;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-solarized-light .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-terminal-theme.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px black;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-terminal-theme .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@
|
|||
}
|
||||
.ace-tm.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px white;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.ace-tm .ace_marker-layer .ace_step {
|
||||
background: rgb(252, 255, 0);
|
||||
|
|
|
|||
|
|
@ -1,139 +0,0 @@
|
|||
.ace-tomorrow-night .ace_gutter {
|
||||
background: #25282c;
|
||||
color: #C5C8C6
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_print-margin {
|
||||
width: 1px;
|
||||
background: #25282c
|
||||
}
|
||||
|
||||
.ace-tomorrow-night {
|
||||
background-color: #1D1F21;
|
||||
color: #C5C8C6
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_cursor {
|
||||
color: #FFFFFF
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_marker-layer .ace_selection {
|
||||
background: #373B41
|
||||
}
|
||||
|
||||
.ace-tomorrow-night.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #1D1F21;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_marker-layer .ace_step {
|
||||
background: rgb(102, 82, 0)
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_marker-layer .ace_bracket {
|
||||
margin: -1px 0 0 -1px;
|
||||
border: 1px solid #4B4E55
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_marker-layer .ace_active-line {
|
||||
background: #282A2E
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_gutter-active-line {
|
||||
background-color: #282A2E
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_marker-layer .ace_selected-word {
|
||||
border: 1px solid #373B41
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_invisible {
|
||||
color: #4B4E55
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_keyword,
|
||||
.ace-tomorrow-night .ace_meta,
|
||||
.ace-tomorrow-night .ace_support.ace_type {
|
||||
color: #C4A400
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_storage,
|
||||
.ace-tomorrow-night .ace_storage.ace_type {
|
||||
color: #327FD7
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_keyword.ace_operator {
|
||||
color: #8ABEB7
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_constant.ace_language{
|
||||
color: #934B9F
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_constant.ace_character,
|
||||
.ace-tomorrow-night .ace_constant.ace_numeric,
|
||||
.ace-tomorrow-night .ace_keyword.ace_other.ace_unit,
|
||||
.ace-tomorrow-night .ace_support.ace_constant,
|
||||
.ace-tomorrow-night .ace_variable.ace_parameter {
|
||||
color: #37BC9B
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_constant.ace_other {
|
||||
color: #CED1CF
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_invalid {
|
||||
color: #CED2CF;
|
||||
background-color: #DF5F5F
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_invalid.ace_deprecated {
|
||||
color: #CED2CF;
|
||||
background-color: #B798BF
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_fold {
|
||||
background-color: #62A5D6;
|
||||
border-color: #C5C8C6
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_entity.ace_name.ace_function,
|
||||
.ace-tomorrow-night .ace_support.ace_function,
|
||||
.ace-tomorrow-night .ace_variable {
|
||||
color: #62A5D6
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_support.ace_class,
|
||||
.ace-tomorrow-night .ace_support.ace_type {
|
||||
color: #F0C674
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_heading,
|
||||
.ace-tomorrow-night .ace_markup.ace_heading,
|
||||
.ace-tomorrow-night .ace_string {
|
||||
color: #CD0000
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_proc_name {
|
||||
color: #04939A
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_backtick {
|
||||
color: #1DAA49
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_entity.ace_name.ace_tag,
|
||||
.ace-tomorrow-night .ace_entity.ace_other.ace_attribute-name,
|
||||
.ace-tomorrow-night .ace_meta.ace_tag,
|
||||
.ace-tomorrow-night .ace_string.ace_regexp,
|
||||
.ace-tomorrow-night .ace_variable {
|
||||
color: #FFFFFF
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_comment {
|
||||
color: #3465A4
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_indent-guide {
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHB3d/8PAAOIAdULw8qMAAAAAElFTkSuQmCC) right repeat-y
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2010, Ajax.org B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ajax.org B.V. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
|
||||
exports.isDark = true;
|
||||
exports.cssClass = "ace-tomorrow-night";
|
||||
exports.cssText = require("../requirejs/text!./the_night_after_tomorrow.css");
|
||||
|
||||
var dom = require("../lib/dom");
|
||||
dom.importCssString(exports.cssText, exports.cssClass);
|
||||
});
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-tomorrow.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #FFFFFF;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-tomorrow .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-tomorrow-night.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #1D1F21;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-tomorrow-night .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
.ace-tomorrow-night-blue.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #002451;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-tomorrow-night-blue .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-tomorrow-night-bright.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #000000;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-tomorrow-night-bright .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
.ace-tomorrow-night-eighties.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #2D2D2D;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-tomorrow-night-eighties .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-twilight.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #141414;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-twilight .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
.ace-vibrant-ink.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #0F0F0F;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-vibrant-ink .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
.ace-xcode.ace_multiselect .ace_selection.ace_start {
|
||||
box-shadow: 0 0 3px 0px #FFFFFF;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.ace-xcode .ace_marker-layer .ace_step {
|
||||
|
|
|
|||
|
|
@ -61,19 +61,15 @@ var UndoManager = function() {
|
|||
*
|
||||
**/
|
||||
this.execute = function(options) {
|
||||
// Normalize deltas for storage.
|
||||
// var deltaSets = this.$serializeDeltas(options.args[0]);
|
||||
var deltaSets = options.args[0];
|
||||
// Add deltas to undo stack.
|
||||
var deltas = options.args[0];
|
||||
this.$doc = options.args[1];
|
||||
if (options.merge && this.hasUndo()){
|
||||
this.dirtyCounter--;
|
||||
deltaSets = this.$undoStack.pop().concat(deltaSets);
|
||||
deltas = this.$undoStack.pop().concat(deltas);
|
||||
}
|
||||
this.$undoStack.push(deltaSets);
|
||||
|
||||
// Reset redo stack.
|
||||
this.$undoStack.push(deltas);
|
||||
this.$redoStack = [];
|
||||
|
||||
if (this.dirtyCounter < 0) {
|
||||
// The user has made a change after undoing past the last clean state.
|
||||
// We can never get back to a clean state now until markClean() is called.
|
||||
|
|
@ -90,11 +86,12 @@ var UndoManager = function() {
|
|||
* @returns {Range} The range of the undo.
|
||||
**/
|
||||
this.undo = function(dontSelect) {
|
||||
var deltaSets = this.$undoStack.pop();
|
||||
var deltas = this.$undoStack.pop();
|
||||
var undoSelectionRange = null;
|
||||
if (deltaSets) {
|
||||
undoSelectionRange = this.$doc.undoChanges(this.$deserializeDeltas(deltaSets), dontSelect);
|
||||
this.$redoStack.push(deltaSets);
|
||||
if (deltas) {
|
||||
undoSelectionRange =
|
||||
this.$doc.undoChanges(deltas, dontSelect);
|
||||
this.$redoStack.push(deltas);
|
||||
this.dirtyCounter--;
|
||||
}
|
||||
|
||||
|
|
@ -108,14 +105,15 @@ var UndoManager = function() {
|
|||
*
|
||||
**/
|
||||
this.redo = function(dontSelect) {
|
||||
var deltaSets = this.$redoStack.pop();
|
||||
var deltas = this.$redoStack.pop();
|
||||
var redoSelectionRange = null;
|
||||
if (deltaSets) {
|
||||
if (deltas) {
|
||||
redoSelectionRange =
|
||||
this.$doc.redoChanges(this.$deserializeDeltas(deltaSets), dontSelect);
|
||||
this.$undoStack.push(deltaSets);
|
||||
this.$doc.redoChanges(deltas, dontSelect);
|
||||
this.$undoStack.push(deltas);
|
||||
this.dirtyCounter++;
|
||||
}
|
||||
|
||||
return redoSelectionRange;
|
||||
};
|
||||
|
||||
|
|
@ -163,52 +161,7 @@ var UndoManager = function() {
|
|||
this.isClean = function() {
|
||||
return this.dirtyCounter === 0;
|
||||
};
|
||||
|
||||
// Serializes deltaSets to reduce memory usage.
|
||||
this.$serializeDeltas = function(deltaSets) {
|
||||
return cloneDeltaSetsObj(deltaSets, $serializeDelta);
|
||||
};
|
||||
|
||||
// Deserializes deltaSets to allow application to the document.
|
||||
this.$deserializeDeltas = function(deltaSets) {
|
||||
return cloneDeltaSetsObj(deltaSets, $deserializeDelta);
|
||||
};
|
||||
|
||||
function $serializeDelta(delta){
|
||||
return {
|
||||
action: delta.action,
|
||||
start: delta.start,
|
||||
end: delta.end,
|
||||
lines: delta.lines.length == 1 ? null : delta.lines,
|
||||
text: delta.lines.length == 1 ? delta.lines[0] : null,
|
||||
};
|
||||
}
|
||||
|
||||
function $deserializeDelta(delta) {
|
||||
return {
|
||||
action: delta.action,
|
||||
start: delta.start,
|
||||
end: delta.end,
|
||||
lines: delta.lines || [delta.text]
|
||||
};
|
||||
}
|
||||
|
||||
function cloneDeltaSetsObj(deltaSets_old, fnGetModifiedDelta) {
|
||||
var deltaSets_new = new Array(deltaSets_old.length);
|
||||
for (var i = 0; i < deltaSets_old.length; i++) {
|
||||
var deltaSet_old = deltaSets_old[i];
|
||||
var deltaSet_new = { group: deltaSet_old.group, deltas: new Array(deltaSet_old.length)};
|
||||
|
||||
for (var j = 0; j < deltaSet_old.deltas.length; j++) {
|
||||
var delta_old = deltaSet_old.deltas[j];
|
||||
deltaSet_new.deltas[j] = fnGetModifiedDelta(delta_old);
|
||||
}
|
||||
|
||||
deltaSets_new[i] = deltaSet_new;
|
||||
}
|
||||
return deltaSets_new;
|
||||
}
|
||||
|
||||
|
||||
}).call(UndoManager.prototype);
|
||||
|
||||
exports.UndoManager = UndoManager;
|
||||
|
|
|
|||
|
|
@ -615,7 +615,7 @@ var VirtualRenderer = function(container, theme) {
|
|||
* @returns {DOMElement}
|
||||
**/
|
||||
this.getMouseEventTarget = function() {
|
||||
return this.scroller;
|
||||
return this.content;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -919,8 +919,6 @@ var VirtualRenderer = function(container, theme) {
|
|||
(this.$minLines||1) * this.lineHeight,
|
||||
Math.min(maxHeight, height)
|
||||
) + this.scrollMargin.v + (this.$extraHeight || 0);
|
||||
if (this.$horizScroll)
|
||||
desiredHeight += this.scrollBarH.getHeight();
|
||||
var vScroll = height > maxHeight;
|
||||
|
||||
if (desiredHeight != this.desiredHeight ||
|
||||
|
|
@ -941,6 +939,9 @@ var VirtualRenderer = function(container, theme) {
|
|||
};
|
||||
|
||||
this.$computeLayerConfig = function() {
|
||||
if (this.$maxLines && this.lineHeight > 1)
|
||||
this.$autosize();
|
||||
|
||||
var session = this.session;
|
||||
var size = this.$size;
|
||||
|
||||
|
|
@ -948,6 +949,9 @@ var VirtualRenderer = function(container, theme) {
|
|||
var screenLines = this.session.getScreenLength();
|
||||
var maxHeight = screenLines * this.lineHeight;
|
||||
|
||||
var offset = this.scrollTop % this.lineHeight;
|
||||
var minHeight = size.scrollerHeight + this.lineHeight;
|
||||
|
||||
var longestLine = this.$getLongestLine();
|
||||
|
||||
var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible ||
|
||||
|
|
@ -958,27 +962,20 @@ var VirtualRenderer = function(container, theme) {
|
|||
this.$horizScroll = horizScroll;
|
||||
this.scrollBarH.setVisible(horizScroll);
|
||||
}
|
||||
// autoresize only after updating hscroll to include scrollbar height in desired height
|
||||
if (this.$maxLines && this.lineHeight > 1)
|
||||
this.$autosize();
|
||||
|
||||
var offset = this.scrollTop % this.lineHeight;
|
||||
var minHeight = size.scrollerHeight + this.lineHeight;
|
||||
|
||||
var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd
|
||||
? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd
|
||||
: 0;
|
||||
maxHeight += scrollPastEnd;
|
||||
|
||||
var sm = this.scrollMargin;
|
||||
this.session.setScrollTop(Math.max(-sm.top,
|
||||
Math.min(this.scrollTop, maxHeight - size.scrollerHeight + sm.bottom)));
|
||||
this.session.setScrollTop(Math.max(-this.scrollMargin.top,
|
||||
Math.min(this.scrollTop, maxHeight - size.scrollerHeight + this.scrollMargin.bottom)));
|
||||
|
||||
this.session.setScrollLeft(Math.max(-sm.left, Math.min(this.scrollLeft,
|
||||
longestLine + 2 * this.$padding - size.scrollerWidth + sm.right)));
|
||||
this.session.setScrollLeft(Math.max(-this.scrollMargin.left, Math.min(this.scrollLeft,
|
||||
longestLine + 2 * this.$padding - size.scrollerWidth + this.scrollMargin.right)));
|
||||
|
||||
var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible ||
|
||||
size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop > sm.top);
|
||||
size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop);
|
||||
var vScrollChanged = this.$vScroll !== vScroll;
|
||||
if (vScrollChanged) {
|
||||
this.$vScroll = vScroll;
|
||||
|
|
|
|||
|
|
@ -36,40 +36,26 @@ if (typeof process !== "undefined") {
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var Editor = require("./edit_session").Editor;
|
||||
var EditSession = require("./edit_session").EditSession;
|
||||
var VirtualRenderer = require("./virtual_renderer").VirtualRenderer;
|
||||
var assert = require("./test/assertions");
|
||||
|
||||
var editor = null;
|
||||
module.exports = {
|
||||
setUp: function() {
|
||||
if (editor)
|
||||
editor.destroy()
|
||||
"test: screen2text the column should be rounded to the next character edge" : function() {
|
||||
var el = document.createElement("div");
|
||||
|
||||
if (!el.getBoundingClientRect) {
|
||||
console.log("Skipping test: This test only runs in the browser");
|
||||
return;
|
||||
}
|
||||
|
||||
el.style.left = "20px";
|
||||
el.style.top = "30px";
|
||||
el.style.width = "300px";
|
||||
el.style.height = "100px";
|
||||
document.body.appendChild(el);
|
||||
var renderer = new VirtualRenderer(el);
|
||||
var editor = new Editor(renderer);
|
||||
editor.on("destroy", function() {
|
||||
document.body.removeChild(el);
|
||||
});
|
||||
},
|
||||
tearDown: function() {
|
||||
editor && editor.destroy();
|
||||
editor = null;
|
||||
},
|
||||
"test: screen2text the column should be rounded to the next character edge" : function(done) {
|
||||
if (!editor) return done();
|
||||
var renderer = editor.renderer;
|
||||
|
||||
var renderer = new VirtualRenderer(el);
|
||||
renderer.setPadding(0);
|
||||
renderer.setSession(new EditSession("1234"));
|
||||
|
||||
|
|
@ -87,23 +73,7 @@ module.exports = {
|
|||
testPixelToText(10, 0, 0, 1);
|
||||
testPixelToText(14, 0, 0, 1);
|
||||
testPixelToText(15, 0, 0, 2);
|
||||
done();
|
||||
},
|
||||
|
||||
"test scrollmargin + autosize": function(done) {
|
||||
if (!editor) return done();
|
||||
editor.setOptions({
|
||||
maxLines: 100,
|
||||
useWrapMode: true
|
||||
});
|
||||
editor.renderer.setScrollMargin(10, 10);
|
||||
editor.setValue("\n\n");
|
||||
editor.setValue("\n\n\n\n");
|
||||
editor.renderer.once("afterRender", function() {
|
||||
setTimeout(function() {
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
document.body.removeChild(el);
|
||||
}
|
||||
|
||||
// change tab size after setDocument (for text layer)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var Range = require("../range").Range;
|
||||
var Document = require("../document").Document;
|
||||
var lang = require("../lib/lang");
|
||||
|
||||
|
|
@ -13,19 +12,7 @@ var Mirror = exports.Mirror = function(sender) {
|
|||
|
||||
var _self = this;
|
||||
sender.on("change", function(e) {
|
||||
var data = e.data;
|
||||
if (data[0].start) {
|
||||
doc.applyDeltas(data);
|
||||
} else {
|
||||
for (var i = 0; i < data.length; i += 2) {
|
||||
if (Array.isArray(data[i+1])) {
|
||||
var d = {action: "insert", start: data[i], lines: data[i+1]};
|
||||
} else {
|
||||
var d = {action: "remove", start: data[i], end: data[i+1]};
|
||||
}
|
||||
doc.applyDelta(d, true);
|
||||
}
|
||||
}
|
||||
doc.applyDeltas(e.data);
|
||||
if (_self.$timeout)
|
||||
return deferredUpdate.schedule(_self.$timeout);
|
||||
_self.onUpdate();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
"no use strict";
|
||||
;(function(window) {
|
||||
if (typeof window.window != "undefined" && window.document)
|
||||
return;
|
||||
if (window.require && window.define)
|
||||
if (typeof window.window != "undefined" && window.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.console = function() {
|
||||
var msgs = Array.prototype.slice.call(arguments, 0);
|
||||
|
|
@ -20,7 +19,6 @@ window.ace = window;
|
|||
window.onerror = function(message, file, line, col, err) {
|
||||
postMessage({type: "error", data: {
|
||||
message: message,
|
||||
data: err.data,
|
||||
file: file,
|
||||
line: line,
|
||||
col: col,
|
||||
|
|
@ -39,7 +37,7 @@ window.normalizeModule = function(parentId, moduleName) {
|
|||
var base = parentId.split("/").slice(0, -1).join("/");
|
||||
moduleName = (base ? base + "/" : "") + moduleName;
|
||||
|
||||
while (moduleName.indexOf(".") !== -1 && previous != moduleName) {
|
||||
while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
|
||||
var previous = moduleName;
|
||||
moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
|
||||
}
|
||||
|
|
@ -48,7 +46,7 @@ window.normalizeModule = function(parentId, moduleName) {
|
|||
return moduleName;
|
||||
};
|
||||
|
||||
window.require = function require(parentId, id) {
|
||||
window.require = function(parentId, id) {
|
||||
if (!id) {
|
||||
id = parentId;
|
||||
parentId = null;
|
||||
|
|
@ -66,36 +64,17 @@ window.require = function require(parentId, id) {
|
|||
}
|
||||
return module.exports;
|
||||
}
|
||||
|
||||
|
||||
var chunks = id.split("/");
|
||||
if (!window.require.tlns)
|
||||
return console.log("unable to load " + id);
|
||||
|
||||
var path = resolveModuleId(id, window.require.tlns);
|
||||
if (path.slice(-3) != ".js") path += ".js";
|
||||
chunks[0] = window.require.tlns[chunks[0]] || chunks[0];
|
||||
var path = chunks.join("/") + ".js";
|
||||
|
||||
window.require.id = id;
|
||||
window.require.modules[id] = {}; // prevent infinite loop on broken modules
|
||||
importScripts(path);
|
||||
return window.require(parentId, id);
|
||||
};
|
||||
function resolveModuleId(id, paths) {
|
||||
var testPath = id, tail = "";
|
||||
while (testPath) {
|
||||
var alias = paths[testPath];
|
||||
if (typeof alias == "string") {
|
||||
return alias + tail;
|
||||
} else if (alias) {
|
||||
return alias.location.replace(/\/*$/, "/") + (tail || alias.main || alias.name);
|
||||
} else if (alias === false) {
|
||||
return "";
|
||||
}
|
||||
var i = testPath.lastIndexOf("/");
|
||||
if (i === -1) break;
|
||||
tail = testPath.substr(i) + tail;
|
||||
testPath = testPath.slice(0, i);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
window.require.modules = {};
|
||||
window.require.tlns = {};
|
||||
|
||||
|
|
@ -121,9 +100,9 @@ window.define = function(id, deps, factory) {
|
|||
}
|
||||
|
||||
if (!deps.length)
|
||||
// If there is no dependencies, we inject "require", "exports" and
|
||||
// "module" as dependencies, to provide CommonJS compatibility.
|
||||
deps = ["require", "exports", "module"];
|
||||
// If there is no dependencies, we inject 'require', 'exports' and
|
||||
// 'module' as dependencies, to provide CommonJS compatibility.
|
||||
deps = ['require', 'exports', 'module'];
|
||||
|
||||
var req = function(childId) {
|
||||
return window.require(id, childId);
|
||||
|
|
@ -134,16 +113,16 @@ window.define = function(id, deps, factory) {
|
|||
factory: function() {
|
||||
var module = this;
|
||||
var returnExports = factory.apply(this, deps.map(function(dep) {
|
||||
switch (dep) {
|
||||
// Because "require", "exports" and "module" aren't actual
|
||||
// dependencies, we must handle them seperately.
|
||||
case "require": return req;
|
||||
case "exports": return module.exports;
|
||||
case "module": return module;
|
||||
// But for all other dependencies, we can just go ahead and
|
||||
// require them.
|
||||
default: return req(dep);
|
||||
}
|
||||
switch(dep) {
|
||||
// Because 'require', 'exports' and 'module' aren't actual
|
||||
// dependencies, we must handle them seperately.
|
||||
case 'require': return req;
|
||||
case 'exports': return module.exports;
|
||||
case 'module': return module;
|
||||
// But for all other dependencies, we can just go ahead and
|
||||
// require them.
|
||||
default: return req(dep);
|
||||
}
|
||||
}));
|
||||
if (returnExports)
|
||||
module.exports = returnExports;
|
||||
|
|
@ -152,10 +131,9 @@ window.define = function(id, deps, factory) {
|
|||
};
|
||||
};
|
||||
window.define.amd = {};
|
||||
require.tlns = {};
|
||||
|
||||
window.initBaseUrls = function initBaseUrls(topLevelNamespaces) {
|
||||
for (var i in topLevelNamespaces)
|
||||
require.tlns[i] = topLevelNamespaces[i];
|
||||
require.tlns = topLevelNamespaces;
|
||||
};
|
||||
|
||||
window.initSender = function initSender() {
|
||||
|
|
@ -195,23 +173,21 @@ var sender = window.sender = null;
|
|||
|
||||
window.onmessage = function(e) {
|
||||
var msg = e.data;
|
||||
if (msg.event && sender) {
|
||||
sender._signal(msg.event, msg.data);
|
||||
}
|
||||
else if (msg.command) {
|
||||
if (msg.command) {
|
||||
if (main[msg.command])
|
||||
main[msg.command].apply(main, msg.args);
|
||||
else if (window[msg.command])
|
||||
window[msg.command].apply(window, msg.args);
|
||||
else
|
||||
throw new Error("Unknown command:" + msg.command);
|
||||
}
|
||||
else if (msg.init) {
|
||||
window.initBaseUrls(msg.tlns);
|
||||
else if (msg.init) {
|
||||
initBaseUrls(msg.tlns);
|
||||
require("ace/lib/es5-shim");
|
||||
sender = window.sender = window.initSender();
|
||||
sender = window.sender = initSender();
|
||||
var clazz = require(msg.module)[msg.classname];
|
||||
main = window.main = new clazz(sender);
|
||||
}
|
||||
else if (msg.event && sender) {
|
||||
sender._signal(msg.event, msg.data);
|
||||
}
|
||||
};
|
||||
})(this);
|
||||
|
|
@ -162,22 +162,19 @@ var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) {
|
|||
doc.on("change", this.changeListener);
|
||||
};
|
||||
|
||||
this.changeListener = function(delta) {
|
||||
this.changeListener = function(e) {
|
||||
if (!this.deltaQueue) {
|
||||
this.deltaQueue = [];
|
||||
this.deltaQueue = [e.data];
|
||||
setTimeout(this.$sendDeltaQueue, 0);
|
||||
}
|
||||
if (delta.action == "insert")
|
||||
this.deltaQueue.push(delta.start, delta.lines);
|
||||
else
|
||||
this.deltaQueue.push(delta.start, delta.end);
|
||||
} else
|
||||
this.deltaQueue.push(e.data);
|
||||
};
|
||||
|
||||
this.$sendDeltaQueue = function() {
|
||||
var q = this.deltaQueue;
|
||||
if (!q) return;
|
||||
this.deltaQueue = null;
|
||||
if (q.length > 50 && q.length > this.$doc.getLength() >> 1) {
|
||||
if (q.length > 20 && q.length > this.$doc.getLength() >> 1) {
|
||||
this.call("setValue", [this.$doc.getValue()]);
|
||||
} else
|
||||
this.emit("change", {data: q});
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ http.createServer(function(req, res) {
|
|||
if (req.method == "PUT") {
|
||||
if (!allowSave)
|
||||
return error(res, 404, "Saving not allowed pass --allow-save to enable");
|
||||
return save(req, res, filename);
|
||||
save(req, res, filename);
|
||||
}
|
||||
|
||||
fs.exists(filename, function(exists) {
|
||||
|
|
@ -86,7 +86,6 @@ function save(req, res, filePath) {
|
|||
}
|
||||
res.statusCode = 200;
|
||||
res.end("OK");
|
||||
console.log("saved ", filePath);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
105
tool/lib.js
105
tool/lib.js
|
|
@ -14,16 +14,8 @@ exports.parsePlist = function(xmlOrJSON, callback) {
|
|||
});
|
||||
} else {
|
||||
try {
|
||||
xmlOrJSON = xmlOrJSON.replace(
|
||||
/("(?:\\.|[^"])*")|(?:,\s*)+([\]\}])|(\w+)\s*:|([\]\}]\s*[\[\{])|(\/\/.*|\/\*(?:[^\*]|\*(?=[^\/]))*?\*\/)/g,
|
||||
function(_, str, extraComma, noQuote, missingComma, comment) {
|
||||
if (comment)
|
||||
return "";
|
||||
if (missingComma)
|
||||
return missingComma[0] + "," + missingComma.slice(1);
|
||||
return str || extraComma || '"' + noQuote + '":';
|
||||
});
|
||||
json = JSON.parse(xmlOrJSON);
|
||||
xmlOrJSON = xmlOrJSON.replace(/^\s*\/\/.*/gm, "");
|
||||
json = JSON.parse(xmlOrJSON)
|
||||
} catch(e) {
|
||||
json = cson.parse(xmlOrJSON);
|
||||
}
|
||||
|
|
@ -32,101 +24,10 @@ exports.parsePlist = function(xmlOrJSON, callback) {
|
|||
return json;
|
||||
};
|
||||
|
||||
|
||||
exports.formatJSON = function(object, initialIndent) {
|
||||
return JSON.stringify(object, null, 4).replace(/^/gm, initialIndent||"");
|
||||
return util.inspect(object, false, 40).replace(/^/gm, initialIndent||"");
|
||||
};
|
||||
|
||||
exports.formatJS = function(object, initialIndent) {
|
||||
return formatJS(object, 4, initialIndent);
|
||||
};
|
||||
|
||||
function formatJS(object, indent, initialIndent) {
|
||||
if (typeof indent == "number")
|
||||
indent = Array(indent + 1).join(" ");
|
||||
|
||||
function $format(buffer, totalIndent, state, o) {
|
||||
if (typeof o != "object" || !o) {
|
||||
if (typeof o == "string")
|
||||
buffer.push(JSON.stringify(o));
|
||||
else
|
||||
buffer.push("" + o);
|
||||
}
|
||||
else if (Array.isArray(o)) {
|
||||
buffer.push("[")
|
||||
|
||||
var len = totalIndent.length
|
||||
var oneLine = true;
|
||||
for (var i = 0; i < o.length; i++) {
|
||||
if (typeof o[i] == "string") {
|
||||
len += o[i].length + 2
|
||||
} else if (!o[i]) {
|
||||
len += (o[i] + "").length
|
||||
} else {
|
||||
oneLine = false;
|
||||
break;
|
||||
}
|
||||
len += 2;
|
||||
if (len > 60) {
|
||||
oneLine = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < o.length; i++) {
|
||||
if (o[i] && typeof o[i] == "object") {
|
||||
$format(buffer, totalIndent, state, o[i]);
|
||||
if (i < o.length - 1)
|
||||
buffer.push(", ");
|
||||
} else {
|
||||
if (oneLine)
|
||||
i && buffer.push(" ");
|
||||
else
|
||||
buffer.push("\n", totalIndent + indent)
|
||||
$format(buffer, totalIndent + indent, state, o[i]);
|
||||
if (i < o.length - 1)
|
||||
buffer.push(",");
|
||||
}
|
||||
|
||||
}
|
||||
if (!oneLine && buffer[buffer.length - 1] != "}")
|
||||
buffer.push("\n" + totalIndent)
|
||||
buffer.push("]")
|
||||
}
|
||||
else {
|
||||
var keys = Object.keys(o);
|
||||
buffer.push("{", "\n");
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
buffer.push(totalIndent + indent);
|
||||
if (/^\w+$/.test(keys[i]))
|
||||
buffer.push(keys[i]);
|
||||
else
|
||||
buffer.push(JSON.stringify(keys[i]));
|
||||
buffer.push(": ")
|
||||
|
||||
if (keys[i] == "regex" && typeof o[keys[i]] == "string") {
|
||||
try {
|
||||
var re = new RegExp(o[keys[i]]);
|
||||
buffer.push("/" + re.source.replace(/\\.|\//g, function(f) {
|
||||
return f.length == 1 ? "\\" + f : f;
|
||||
}) + "/");
|
||||
} catch(e) {
|
||||
$format(buffer, totalIndent + indent, state, o[keys[i]]);
|
||||
}
|
||||
} else {
|
||||
$format(buffer, totalIndent + indent, state, o[keys[i]]);
|
||||
}
|
||||
|
||||
if (i < keys.length - 1)
|
||||
buffer.push(",", "\n");
|
||||
}
|
||||
buffer.push("\n", totalIndent, "}");
|
||||
}
|
||||
}
|
||||
var buffer = [];
|
||||
$format(buffer, initialIndent || "", {}, object);
|
||||
return buffer.join("");
|
||||
}
|
||||
|
||||
exports.fillTemplate = function(template, replacements) {
|
||||
return template.replace(/%(.+?)%/g, function(str, m) {
|
||||
|
|
|
|||
|
|
@ -126,8 +126,8 @@ function handleSaveResult(err, editor) {
|
|||
return log(
|
||||
"Write access to this file is disabled.\n"+
|
||||
"To enable saving your changes to disk, clone the Ace repository\n"+
|
||||
"and run the included web server with the --allow-save option\n"+
|
||||
"`node static.js --allow-save` or `static.py --puttable=*`"
|
||||
"and run the included web server with the --allow-write option\n"+
|
||||
"`node static.js --allow-write` or `static.py --puttable=*`"
|
||||
);
|
||||
}
|
||||
editor.session.getUndoManager().markClean();
|
||||
|
|
|
|||
|
|
@ -662,10 +662,10 @@ function convertTmLanguage(name, langStr) {
|
|||
|
||||
var languageHighlightRules = lib.fillTemplate(modeHighlightTemplate, {
|
||||
language: languageNameSanitized,
|
||||
languageTokens: lib.formatJS(patterns, " ").trim(),
|
||||
languageTokens: lib.formatJSON(patterns, " ").trim(),
|
||||
uuid: language.uuid,
|
||||
name: name,
|
||||
metaData: lib.formatJS(language, "").trim()
|
||||
metaData: lib.formatJSON(language, " ").trim()
|
||||
});
|
||||
|
||||
if (devMode) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue