update ace

This commit is contained in:
nightwing 2018-03-04 23:10:40 +04:00
parent 882e4b7d16
commit f423218a7e
73 changed files with 3628 additions and 2881 deletions

View File

@ -42,6 +42,7 @@ require("./lib/fixoldbrowsers");
var dom = require("./lib/dom");
var event = require("./lib/event");
var Range = require("./range").Range;
var Editor = require("./editor").Editor;
var EditSession = require("./edit_session").EditSession;
var UndoManager = require("./undomanager").UndoManager;
@ -92,7 +93,7 @@ exports.edit = function(el, options) {
el = dom.createElement("pre");
oldNode.parentNode.replaceChild(el, oldNode);
} else if (el) {
value = dom.getInnerText(el);
value = el.textContent;
el.innerHTML = "";
}
@ -126,7 +127,9 @@ exports.createEditSession = function(text, mode) {
doc.setUndoManager(new UndoManager());
return doc;
};
exports.Range = Range;
exports.EditSession = EditSession;
exports.UndoManager = UndoManager;
exports.version = "1.2.9";
exports.VirtualRenderer = Renderer;
exports.version = "1.3.1";
});

View File

@ -381,14 +381,28 @@ var Autocomplete = function() {
tooltipNode.style.top = popup.container.style.top;
tooltipNode.style.bottom = popup.container.style.bottom;
tooltipNode.style.display = "block";
if (window.innerWidth - rect.right < 320) {
tooltipNode.style.right = window.innerWidth - rect.left + "px";
tooltipNode.style.left = "";
if (rect.left < 320) {
if(popup.isTopdown) {
tooltipNode.style.top = rect.bottom + "px";
tooltipNode.style.left = rect.left + "px";
tooltipNode.style.right = "";
tooltipNode.style.bottom = "";
} else {
tooltipNode.style.top = popup.container.offsetTop - tooltipNode.offsetHeight + "px";
tooltipNode.style.left = rect.left + "px";
tooltipNode.style.right = "";
tooltipNode.style.bottom = "";
}
} else {
tooltipNode.style.right = window.innerWidth - rect.left + "px";
tooltipNode.style.left = "";
}
} else {
tooltipNode.style.left = (rect.right + 1) + "px";
tooltipNode.style.right = "";
}
tooltipNode.style.display = "block";
};
this.hideDocTooltip = function() {
@ -475,24 +489,35 @@ var FilteredList = function(array, filterText) {
if (this.exactMatch) {
if (needle !== caption.substr(0, needle.length))
continue loop;
}else{
// caption char iteration is faster in Chrome but slower in Firefox, so lets use indexOf
for (var j = 0; j < needle.length; j++) {
// TODO add penalty on case mismatch
var i1 = caption.indexOf(lower[j], lastIndex + 1);
var i2 = caption.indexOf(upper[j], lastIndex + 1);
index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2;
if (index < 0)
continue loop;
distance = index - lastIndex - 1;
if (distance > 0) {
// first char mismatch should be more sensitive
if (lastIndex === -1)
penalty += 10;
penalty += distance;
} else {
/**
* It is for situation then, for example, we find some like 'tab' in item.value="Check the table"
* and want to see "Check the TABle" but see "Check The tABle".
*/
var a;
if ((a = caption.toLowerCase().indexOf(lower)) > -1) {
for (var k = a; k < a + lower.length; k++) {
matchMask = matchMask | (1 << k);
}
} else {
// caption char iteration is faster in Chrome but slower in Firefox, so lets use indexOf
for (var j = 0; j < needle.length; j++) {
// TODO add penalty on case mismatch
var i1 = caption.indexOf(lower[j], lastIndex + 1);
var i2 = caption.indexOf(upper[j], lastIndex + 1);
index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2;
if (index < 0)
continue loop;
distance = index - lastIndex - 1;
if (distance > 0) {
// first char mismatch should be more sensitive
if (lastIndex === -1)
penalty += 10;
penalty += distance;
}
matchMask = matchMask | (1 << index);
lastIndex = index;
}
matchMask = matchMask | (1 << index);
lastIndex = index;
}
}
item.matchMask = matchMask;

View File

@ -57,7 +57,7 @@ exports.commands = [{
name: "goToNextError",
bindKey: bindKey("Alt-E", "F4"),
exec: function(editor) {
config.loadModule("ace/ext/error_marker", function(module) {
config.loadModule("./ext/error_marker", function(module) {
module.showErrorMarker(editor, 1);
});
},
@ -67,7 +67,7 @@ exports.commands = [{
name: "goToPreviousError",
bindKey: bindKey("Alt-Shift-E", "Shift-F4"),
exec: function(editor) {
config.loadModule("ace/ext/error_marker", function(module) {
config.loadModule("./ext/error_marker", function(module) {
module.showErrorMarker(editor, -1);
});
},

View File

@ -575,12 +575,13 @@ var Document = function(textOrLines) {
return;
}
if (isInsert && delta.lines.length > 20000)
if (isInsert && delta.lines.length > 20000) {
this.$splitAndapplyLargeDelta(delta, 20000);
// Apply.
applyDelta(this.$lines, delta, doNotValidate);
this._signal("change", delta);
}
else {
applyDelta(this.$lines, delta, doNotValidate);
this._signal("change", delta);
}
};
this.$splitAndapplyLargeDelta = function(delta, MAX) {
@ -594,21 +595,12 @@ var Document = function(textOrLines) {
// 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 l = lines.length - MAX + 1;
var row = delta.start.row;
var column = delta.start.column;
var from = 0, to = 0;
do {
from = to;
for (var from = 0, to = 0; from < l; 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),
@ -616,7 +608,12 @@ var Document = function(textOrLines) {
action: delta.action,
lines: chunk
}, true);
} while(true);
}
// Update remaining delta.
delta.lines = lines.slice(from);
delta.start.row = row + from;
delta.start.column = column;
this.applyDelta(delta, true);
};
/**
@ -656,7 +653,7 @@ var Document = function(textOrLines) {
if (index < 0)
return {row: i, column: index + lines[i].length + newlineLength};
}
return {row: l-1, column: lines[l-1].length};
return {row: l-1, column: index + lines[l-1].length + newlineLength};
};
/**

View File

@ -30,7 +30,6 @@
if (typeof process !== "undefined") {
require("amd-loader");
require("./test/mockdom");
}
define(function(require, exports, module) {
@ -102,6 +101,31 @@ module.exports = {
doc.insertFullLines(2, ["aa", "bb"]);
assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n"));
},
"test: insertInLine" : function() {
var doc = new Document(["12", "34"]);
var deltas = [];
doc.on("change", function(e) { deltas.push(e); });
doc.insertInLine({row: 0, column: 1}, "a");
assert.equal(doc.getValue(), ["1a2", "34"].join("\n"));
doc.insertInLine({row: 10, column: Infinity}, "b");
assert.equal(doc.getValue(), ["1a2", "34b"].join("\n"));
doc.insertInLine({row: undefined, column: Infinity}, "x");
assert.equal(doc.getValue(), ["1a2", "34b", "x"].join("\n"));
doc.insertInLine({row: -1, column: Infinity}, "z");
assert.equal(doc.getValue(), ["1a2z", "34b", "x"].join("\n"));
doc.removeInLine(0, 1, 2);
assert.equal(doc.getValue(), ["12z", "34b", "x"].join("\n"));
doc.removeInLine(0, 2, 10);
assert.equal(doc.getValue(), ["12", "34b", "x"].join("\n"));
doc.removeNewLine(1);
assert.equal(doc.getValue(), ["12", "34bx"].join("\n"));
doc.removeNewLine(1);
assert.equal(doc.getValue(), ["12", "34bx"].join("\n"));
},
"test: insert lines in the middle" : function() {
var doc = new Document(["12", "34"]);
@ -249,6 +273,11 @@ module.exports = {
doc.setNewLineMode("unix");
assert.equal(doc.getValue(), ["1", "2", "3"].join("\n"));
assert.equal(doc.getNewLineMode(), "unix");
assert.ok(doc.isNewLine("\r"));
assert.ok(doc.isNewLine("\n"));
assert.ok(doc.isNewLine("\r\n"));
assert.notOk(doc.isNewLine("\n\r"));
},
"test: set new line mode to 'windows' should use '\\r\\n' as new lines": function() {
@ -311,20 +340,48 @@ module.exports = {
"test: inserting huge delta": function() {
var doc = new Document("");
var val = "";
var MAX = 0xF000;
for (var i = 0; i < 10 * MAX; i++) {
var MAX = 20000 - 1;
for (var i = 0; i < 4 * MAX; i++) {
val += i + "\n";
}
var changeCount = 0;
function testDelta(delta) {
changeCount++;
assert.equal(delta.lines.length, MAX + 1);
}
doc.on("change", testDelta);
doc.setValue(val);
doc.off("change", testDelta);
assert.equal(changeCount, 4);
assert.equal(doc.getValue(), val);
for (var i = 3 * MAX + 2; i >= 3 * MAX - 2; i--) {
for (var i = 2 * MAX + 20; i >= 2 * MAX - 20; i--) {
val = doc.getLines(0, i).join("\n");
doc.setValue("\nab");
assert.equal(doc.getValue(), "\nab");
doc.insert({row: 1, column: 1}, val);
assert.equal(doc.getValue(), "\na" + val + "b");
}
},
"test: indexToPosition": function() {
function test(value) {
var doc = new Document(value);
var secondLine = value.indexOf("|");
for (var i = -2; i < value.length + 4; i++) {
if (value[i - 1] == "\r") continue;
var pos = doc.indexToPosition(i);
var text = doc.getTextRange({start: {row: 0, column: 0}, end: pos});
assert.equal(text, value.substring(0, i));
assert.equal(doc.positionToIndex(pos), i);
if (i >= secondLine) {
assert.deepEqual(doc.indexToPosition(i - secondLine, 1), pos);
assert.equal(doc.positionToIndex(pos, 1), i - secondLine);
}
}
}
test("abc\n|defx\ngh");
test("abc\r\n|defx\r\ngh");
}
};

View File

@ -2540,6 +2540,10 @@ config.defineOptions(EditSession.prototype, "session", {
handlesSet: true
},
navigateWithinSoftTabs: {initialValue: false},
foldStyle: {
set: function(val) {this.setFoldStyle(val);},
handlesSet: true
},
overwrite: {
set: function(val) {this._signal("changeOverwrite");},
initialValue: false

View File

@ -252,7 +252,7 @@ Editor.$uid = 0;
*
**/
this.setKeyboardHandler = function(keyboardHandler, cb) {
if (keyboardHandler && typeof keyboardHandler === "string") {
if (keyboardHandler && typeof keyboardHandler === "string" && keyboardHandler != "ace") {
this.$keybindingId = keyboardHandler;
var _self = this;
config.loadModule(["keybinding", keyboardHandler], function(module) {
@ -504,7 +504,7 @@ Editor.$uid = 0;
*/
this.getFontSize = function () {
return this.getOption("fontSize") ||
dom.computedStyle(this.container, "fontSize");
dom.computedStyle(this.container).fontSize;
};
/**
@ -640,12 +640,13 @@ Editor.$uid = 0;
* Brings the current `textInput` into focus.
**/
this.focus = function() {
// Safari needs the timeout
// iOS and Firefox need it called immediately
// to be on the save side we do both
// focusing after timeout is not needed now, but some code using ace
// depends on being able to call focus when textarea is not visible,
// so to keep backwards compatibility we keep this until the next major release
var _self = this;
setTimeout(function() {
_self.textInput.focus();
if (!_self.isFocused())
_self.textInput.focus();
});
this.textInput.focus();
};
@ -753,8 +754,10 @@ Editor.$uid = 0;
var highlight;
if (this.$highlightActiveLine) {
if ((this.$selectionStyle != "line" || !this.selection.isMultiLine()))
if (this.$selectionStyle != "line" || !this.selection.isMultiLine())
highlight = this.getCursorPosition();
if (this.renderer.theme && this.renderer.theme.$selectionColorConflict && !this.selection.isEmpty())
highlight = false;
if (this.renderer.$maxLines && this.session.getLength() === 1 && !(this.renderer.$minLines > 1))
highlight = false;
}
@ -2648,8 +2651,7 @@ config.defineOptions(Editor.prototype, "editor", {
},
readOnly: {
set: function(readOnly) {
// disabled to not break vim mode!
// this.textInput.setReadOnly(readOnly);
this.textInput.setReadOnly(readOnly);
this.$resetCursorStyle();
},
initialValue: false
@ -2712,11 +2714,12 @@ config.defineOptions(Editor.prototype, "editor", {
scrollPastEnd: "renderer",
fixedWidthGutter: "renderer",
theme: "renderer",
hasCssTransforms: "renderer",
scrollSpeed: "$mouseHandler",
dragDelay: "$mouseHandler",
dragEnabled: "$mouseHandler",
focusTimout: "$mouseHandler",
focusTimeout: "$mouseHandler",
tooltipFollowsMouse: "$mouseHandler",
firstLineNumber: "session",
@ -2724,6 +2727,7 @@ config.defineOptions(Editor.prototype, "editor", {
newLineMode: "session",
useWorker: "session",
useSoftTabs: "session",
navigateWithinSoftTabs: "session",
tabSize: "session",
wrap: "session",
indentedSoftWrap: "session",

View File

@ -0,0 +1,542 @@
/* ***** 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 ***** */
if (typeof process !== "undefined") {
require("amd-loader");
require("./test/mockdom");
}
define(function(require, exports, module) {
"use strict";
var ace = require("./ace");
var EditSession = require("./edit_session").EditSession;
var Editor = require("./editor").Editor;
var MockRenderer = require("./test/mockrenderer").MockRenderer;
var JavaScriptMode = require("./mode/javascript").Mode;
var HTMLMode = require("./mode/html").Mode;
var assert = require("./test/assertions");
var editor;
var exec = function(name, times, args) {
do {
editor.commands.exec(name, editor, args);
} while(times --> 1);
};
module.exports = {
"test modifyNumber": function() {
editor = new Editor(new MockRenderer());
editor.setValue("999");
editor.execCommand(editor.commands.byName.modifyNumberUp);
assert.equal(editor.getValue(), "1000");
editor.setValue("999f");
editor.execCommand(editor.commands.byName.modifyNumberUp);
assert.equal(editor.getValue(), "999f");
editor.setValue("1000");
editor.execCommand(editor.commands.byName.modifyNumberDown);
assert.equal(editor.getValue(), "999");
editor.setValue("1000.1");
editor.execCommand(editor.commands.byName.modifyNumberDown);
assert.equal(editor.getValue(), "1000.0");
editor.setValue("123.3", 1);
exec("gotoleft", 2);
editor.execCommand(editor.commands.byName.modifyNumberDown);
assert.equal(editor.getValue(), "122.3");
},
"test duplicateSelection": function() {
editor = new Editor(new MockRenderer());
editor.setValue("123.3", 1);
exec("selectleft", 2);
editor.execCommand(editor.commands.byName.duplicateSelection);
assert.equal(editor.getValue(), "123.3.3");
editor.setValue("124.3", 1);
exec("gotoleft", 3);
exec("selectright", 2);
editor.execCommand(editor.commands.byName.duplicateSelection);
assert.equal(editor.getValue(), "124.4.3");
editor.clearSelection();
editor.execCommand(editor.commands.byName.duplicateSelection);
assert.equal(editor.getValue(), "124.4.3\n124.4.3");
},
"test editor find": function() {
editor = new Editor(new MockRenderer());
editor.setValue("for for foo", 1);
exec("gotoleft", 8);
exec("selectleft", 3);
editor.execCommand(editor.commands.byName.findnext);
assert.range(editor.selection.getRange(), 0, 4, 0, 7);
editor.setValue("for for for foo", 1);
exec("gotoleft", 8);
exec("selectleft", 3);
editor.execCommand(editor.commands.byName.findprevious);
assert.range(editor.selection.getRange(), 0, 0, 0, 3);
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 8);
editor.execCommand(editor.commands.byName.selectOrFindNext);
assert.range(editor.selection.getRange(), 0, 4, 0, 7);
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 7);
exec("selectright", 3);
editor.execCommand(editor.commands.byName.selectOrFindNext);
assert.range(editor.selection.getRange(), 0, 12, 0, 15);
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 8);
editor.execCommand(editor.commands.byName.selectOrFindPrevious);
assert.range(editor.selection.getRange(), 0, 4, 0, 7);
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 7);
exec("selectright", 3);
editor.execCommand(editor.commands.byName.selectOrFindPrevious);
assert.range(editor.selection.getRange(), 0, 0, 0, 3);
},
"test overwrite": function() {
editor = new Editor(new MockRenderer());
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 7);
editor.execCommand(editor.commands.byName.overwrite);
exec("insertstring", 1, "b");
assert.equal(editor.getValue(),"foo for boo foo");
},
"test selections": function() {
editor = new Editor(new MockRenderer(5));
editor.setValue("foo for foo foo\nfoo for foo foo", 1);
exec("gotoleft", 7);
editor.execCommand(editor.commands.byName.selecttostart);
assert.range(editor.selection.getRange(), 0, 0, 1, 8);
editor.setValue("foo for foo foo\nfsdfsd232", 1);
exec("gotoleft", 3);
editor.execCommand(editor.commands.byName.selectup);
assert.range(editor.selection.getRange(), 0, 6, 1, 6);
editor.setValue("foo for foo foo\nfsdfsd232", 1);
exec("gotoleft", 9);
editor.execCommand(editor.commands.byName.selecttoend);
assert.range(editor.selection.getRange(), 1, 0, 1, 9);
editor.setValue("foo for foo foo\nfsdfsd232", 1);
exec("gotostart", 1);
exec("gotoright", 3);
editor.execCommand(editor.commands.byName.selectdown);
assert.range(editor.selection.getRange(), 0, 3, 1, 3);
editor.setValue("foo for foo foo\nfsdfsd232", 1);
exec("gotoleft", 4);
editor.execCommand(editor.commands.byName.selecttolinestart);
assert.range(editor.selection.getRange(), 1, 0, 1, 5);
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 7);
editor.execCommand(editor.commands.byName.selectwordright);
assert.range(editor.selection.getRange(), 0, 8, 0, 11);
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("gotoright", 2);
exec("selectright", 2);
editor.execCommand(editor.commands.byName.selecttolineend);
assert.range(editor.selection.getRange(), 0, 2, 0, 15);
// dublicate command
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("gotoright", 2);
exec("selectright", 2);
editor.execCommand(editor.commands.byName.selectlineend);
assert.range(editor.selection.getRange(), 0, 2, 0, 15);
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 2);
editor.execCommand(editor.commands.byName.selectlinestart);
assert.range(editor.selection.getRange(), 0, 0, 0, 13);
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("gotoright", 3);
exec("selectright", 3);
editor.execCommand(editor.commands.byName.invertSelection);
assert.range(editor.selection.getAllRanges()[0], 0, 0, 0, 3);
assert.range(editor.selection.getAllRanges()[1], 0, 6, 0, 15);
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("selectright", 3);
editor.execCommand(editor.commands.byName.invertSelection);
assert.range(editor.selection.getRange(), 0, 3, 0, 15);
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
editor.execCommand(editor.commands.byName.invertSelection);
assert.range(editor.selection.getRange(), 0, 0, 0, 15);
editor.setValue("foo for foo foo");
editor.execCommand(editor.commands.byName.invertSelection);
assert.range(editor.selection.getRange(), 0, 15, 0, 15);
// ToDO: plenty of matching tests
editor.session.setMode(new HTMLMode);
editor.setValue("<html><head></head> abcd</html>", 1);
exec("gotostart", 1);
exec("gotoright", 3);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 3, 0, 24);
editor.setValue("<html><div><div>abcd</div></html>", 1);
exec("gotostart", 1);
exec("gotoright", 11);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 11, 0, 26);
editor.setValue("<html><div><div>abcd</div></html>", 1);
exec("gotostart", 1);
exec("gotoright", 22);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 20, 0, 22);
editor.setValue("<html>abcd</div></html>", 1);
exec("gotostart", 1);
exec("gotoright", 15);
editor.execCommand(editor.commands.byName.selecttomatching);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 6, 0, 15);
editor.setValue("<html>abcd</div></div></html>", 1);
exec("gotostart", 1);
exec("gotoright", 21);
editor.execCommand(editor.commands.byName.selecttomatching);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 6, 0, 21);
editor.setValue("", 1);
exec("gotostart", 1);
exec("gotoright", 3);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 0, 0, 0);
editor.session.setMode(new JavaScriptMode);
editor.setValue("if (state == 1) {alert(1);}", -1);
exec("gotowordright", 9);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 17, 0, 26);
editor.setValue("if (state == 1) {}", 1);
exec("gotoleft", 1);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 17, 0, 17);
editor.setValue("if (state == 1) {alert(1);}", 1);
editor.selection.moveTo(0, 16);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 16, 0, 16);
editor.setValue("if (state == 1) {alert(1);}", 1);
exec("gotostart", 1);
exec("gotoright", 16);
exec("selectright", 10);
editor.execCommand(editor.commands.byName.selecttomatching);
assert.range(editor.selection.getRange(), 0, 16, 0, 17);
editor.setValue("<html>abcd</div></div></html>", 1);
exec("gotostart", 1);
exec("gotoright", 6);
editor.execCommand(editor.commands.byName.selecttomatching);
// TODO: assert.range should return selection until the </html> instead of </div>
editor.setValue("<html>abcd</div>\n</div></html>", 1);
exec("gotostart", 1);
exec("gotoright", 6);
editor.execCommand(editor.commands.byName.expandtoline);
editor.execCommand(editor.commands.byName.expandtoline);
assert.range(editor.selection.getRange(), 0, 0, 1, 13);
},
"test goto": function() {
editor = new Editor(new MockRenderer());
editor.setValue("foo for foo foo\nfsdfsd232", 1);
editor.execCommand(editor.commands.byName.golineup);
assert.position(editor.getCursorPosition(), 0, 9);
editor.setValue("foo for foo foo\nfsdfsd232\ndfsf", 1);
exec("gotostart", 1);
exec("selectdown", 1);
editor.execCommand(editor.commands.byName.golineup);
assert.position(editor.getCursorPosition(), 0, 0);
editor.setValue("foo for foo foo\nfsdfsd232\ndfsf", 1);
exec("selectup", 1);
editor.execCommand(editor.commands.byName.golinedown);
assert.position(editor.getCursorPosition(), 2, 4);
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("selectright", 2);
editor.execCommand(editor.commands.byName.gotoright);
assert.position(editor.getCursorPosition(), 0, 2);
editor.setValue("foo for foo foo", 1);
editor.execCommand(editor.commands.byName.gotowordleft);
assert.position(editor.getCursorPosition(), 0, 12);
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
editor.execCommand(editor.commands.byName.gotowordright);
assert.position(editor.getCursorPosition(), 0, 3);
},
"test cut/cut_or_delete": function() {
editor = new Editor(new MockRenderer());
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("selectright", 3);
editor.execCommand(editor.commands.byName.cut);
assert.equal(editor.getValue(), " for foo foo");
editor.setValue("foo for foo foo\nfoo", 1);
//exec("gotostart", 1);
exec("selectall", 1);
editor.execCommand(editor.commands.byName.cut);
assert.equal(editor.getValue(), "");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
editor.execCommand(editor.commands.byName.cut);
assert.equal(editor.getValue(), "foo for foo foo");
editor.setValue("foo for foo foo", 1);
editor.execCommand(editor.commands.byName.cut_or_delete);
assert.equal(editor.getValue(), "foo for foo fo");
editor.session.setMode(new JavaScriptMode);
editor.setValue("foo for foo foo", 1);
exec("selectleft", 2);
assert.ok(editor.execCommand("cut_or_delete") == false);
},
"test sortlines": function() {
editor = new Editor(new MockRenderer());
editor.setValue("def\nabd\nacde", 1);
exec("selectall", 1);
editor.execCommand(editor.commands.byName.sortlines);
assert.equal(editor.getValue(), "abd\nacde\ndef");
editor.setValue("def\nabd\nabd", 1);
exec("selectall", 1);
editor.execCommand(editor.commands.byName.sortlines);
assert.equal(editor.getValue(), "abd\nabd\ndef");
},
"test togglecomments/blockcomments": function() {
editor = new Editor(new MockRenderer());
editor.session.setMode(new JavaScriptMode);
editor.setValue("def\nabd\nabd");
editor.execCommand(editor.commands.byName.togglecomment);
assert.equal(editor.getValue(), "// def\n// abd\n// abd");
editor.setValue("def\nabd\nabd");
editor.execCommand(editor.commands.byName.toggleBlockComment);
assert.equal(editor.getValue(), "/*def\nabd\nabd*/");
},
"test redo": function() {
editor = new Editor(new MockRenderer());
editor.setValue("def\nabd\nabd");
exec("selectall", 1);
exec("backspace", 1);
exec("undo", 1);
editor.execCommand(editor.commands.byName.redo);
assert.equal(editor.getValue(), "");
},
"test removetoline": function() {
editor = new Editor(new MockRenderer());
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 3);
editor.execCommand(editor.commands.byName.removetolinestart);
assert.equal(editor.getValue(), "foo");
editor.setValue("foo for foo foo", 1);
exec("selectleft", 3);
editor.execCommand(editor.commands.byName.removetolinestart);
assert.equal(editor.getValue(), "foo for foo ");
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 3);
editor.execCommand(editor.commands.byName.removetolinestarthard);
assert.equal(editor.getValue(), "foo");
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 3);
exec("selectleft", 3);
editor.execCommand(editor.commands.byName.removetolinestarthard);
assert.equal(editor.getValue(), "foo");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("gotoright", 2);
editor.execCommand(editor.commands.byName.removetolineend);
assert.equal(editor.getValue(), "fo");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("selectright", 2);
editor.execCommand(editor.commands.byName.removetolineend);
assert.equal(editor.getValue(), "o for foo foo");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("gotoright", 2);
editor.execCommand(editor.commands.byName.removetolineendhard);
assert.equal(editor.getValue(), "fo");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("gotoright", 2);
exec("selectright", 2);
editor.execCommand(editor.commands.byName.removetolineendhard);
assert.equal(editor.getValue(), "fo");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
editor.execCommand(editor.commands.byName.removewordright);
assert.equal(editor.getValue(), " for foo foo");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("selectright", 1);
editor.execCommand(editor.commands.byName.removewordright);
assert.equal(editor.getValue(), "oo for foo foo");
},
"test indent/outdent": function() {
editor = new Editor(new MockRenderer());
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
editor.execCommand(editor.commands.byName.indent);
assert.equal(editor.getValue()," foo for foo foo");
// TODO: buggy behaviour with autocompletion. For example, when cursor after f in the middle of the word.
editor.setValue("foo for foo foo\nfoo for foo foo", 1);
exec("gotoleft", 3);
exec("selecttostart", 1);
editor.execCommand(editor.commands.byName.indent);
assert.equal(editor.getValue(), " foo for foo foo\n foo for foo foo");
editor.setValue("foo for foo foo\nfoo for foo foo");
editor.execCommand(editor.commands.byName.indent);
assert.equal(editor.getValue(), " foo for foo foo\n foo for foo foo");
editor.setValue("foo for foo foo\nfoo for foo foo", 1);
exec("gotoleft", 3);
exec("selectleft", 2);
editor.execCommand(editor.commands.byName.indent);
assert.equal(editor.getValue(), "foo for foo foo\n foo for foo foo");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("indent", 1);
editor.execCommand(editor.commands.byName.outdent);
assert.equal(editor.getValue(), "foo for foo foo");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
exec("indent", 1);
editor.execCommand(editor.commands.byName.blockoutdent);
assert.equal(editor.getValue(), "foo for foo foo");
editor.setValue("foo for foo foo", 1);
exec("gotostart", 1);
editor.execCommand(editor.commands.byName.blockindent);
assert.equal(editor.getValue()," foo for foo foo");
},
"test splitline": function() {
editor = new Editor(new MockRenderer());
editor.setValue("foo for foo foo", 1);
exec("gotoleft", 3);
editor.execCommand(editor.commands.byName.splitline);
assert.equal(editor.getValue(), "foo for foo \nfoo");
editor.setValue("foo for foo foo", 1);
exec("selectleft", 3);
editor.execCommand(editor.commands.byName.splitline);
assert.equal(editor.getValue(), "foo for foo \n");
},
"test touppercase/tolowercase": function() {
editor = new Editor(new MockRenderer());
editor.setValue("foo for foo foo");
editor.execCommand(editor.commands.byName.touppercase);
assert.equal(editor.getValue(), "FOO FOR FOO FOO");
editor.setValue("FOO for FOO FOO");
editor.execCommand(editor.commands.byName.tolowercase);
assert.equal(editor.getValue(), "foo for foo foo");
},
"test joinlines": function() {
editor = new Editor(new MockRenderer());
editor.setValue("foo for foo foo\nfoo for foo foo");
editor.execCommand(editor.commands.byName.joinlines);
assert.equal(editor.getValue(), "foo for foo foo foo for foo foo");
editor.setValue("foo for foo foo\nfoo for foo foo\nfoo for foo foo", 1);
editor.execCommand(editor.commands.byName.joinlines);
assert.equal(editor.getValue(), "foo for foo foo\nfoo for foo foo\nfoo for foo foo");
editor.setValue("foo for foo foo\nfoo for foo foo\nfoo for foo foo", 1);
exec("gotostart", 1);
exec("selectlineend", 1);
editor.execCommand(editor.commands.byName.joinlines);
assert.equal(editor.getValue(), "foo for foo foo foo for foo foo\nfoo for foo foo");
}
};
});
if (typeof module !== "undefined" && module === require.main) {
require("asyncjs").test.testcase(module.exports).exec();
}

View File

@ -180,10 +180,9 @@ module.exports = {
},
"test: partial word selection 3": function() {
this.selection.moveCursorTo(0, 14);
this.selection.selectWord();
this.selection.selectLeft();
this.selection.shiftSelection(1);
var range = this.selection.getWordRange(0, 14);
range.start.column++;
this.selection.setRange(range);
var range = this.selection.getRange();
assert.equal(this.session.getTextRange(range), "olor");

View File

@ -32,17 +32,217 @@
define(function(require, exports, module) {
"use strict";
var TokenIterator = require("ace/token_iterator").TokenIterator;
var TokenIterator = require("../token_iterator").TokenIterator;
var phpTransform = require("./beautify/php_rules").transform;
function is(token, type) {
return token.type.lastIndexOf(type + ".xml") > -1;
}
// do not indent after singleton tags or <html>
exports.singletonTags = ["area", "base", "br", "col", "command", "embed", "hr", "html", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"];
// insert a line break after block level tags
exports.blockTags = ["article", "aside", "blockquote", "body", "div", "dl", "fieldset", "footer", "form", "head", "header", "html", "nav", "ol", "p", "script", "section", "style", "table", "tbody", "tfoot", "thead", "ul"];
exports.beautify = function(session) {
var iterator = new TokenIterator(session, 0, 0);
var token = iterator.getCurrentToken();
var tabString = session.getTabString();
var singletonTags = exports.singletonTags;
var blockTags = exports.blockTags;
var nextToken;
var breakBefore = false;
var code = "";
var value = "";
var tagName = "";
var indent = 0;
var inBlock = false;
var inComment = false;
var inCase = false;
var onCaseLine = false;
var row;
var curRow = 0;
var rowsToAdd = 0;
var rowTokens = [];
var abort = false;
var i;
var indentNextLine = false;
var context = session.$modeId.split("/").pop();
while (token !== null) {
value = token.value;
curRow = iterator.getCurrentTokenRow();
rowTokens = iterator.$rowTokens;
nextToken = iterator.stepForward();
var code = phpTransform(iterator, context);
// are we in a block tag
if (is(token, "tag-open") && value === "<" && nextToken)
inBlock = (blockTags.indexOf(nextToken.value) !== -1);
// comments
if (is(token, "comment.start")) {
inComment = true;
inBlock = true;
} else if (is(token, "comment.end")) {
inComment = false;
inBlock = false;
}
// html indentation
if (is(token, "tag-open") && value === "</") {
// line break before closing tag unless we just had one
if (is(token, "tag-open") && value === "</" && inBlock && !breakBefore)
rowsToAdd++;
indent--;
inBlock = false;
}
// switch case
onCaseLine = false;
if (token.type === "keyword" && value.match(/^(case|default)$/)) {
onCaseLine = true;
inCase = true;
} else if (token.type === "keyword" && value === "break")
inCase = false;
// add rows
if (curRow != row) {
rowsToAdd = curRow;
if (row)
rowsToAdd -= row;
}
if (rowsToAdd) {
code = code.trimRight();
for (; rowsToAdd > 0; rowsToAdd--)
code += "\n";
breakBefore = true;
// trim value if not in a comment
if (!inComment)
value = value.trimLeft();
}
if (value) {
// whitespace
if (token.type === "keyword" && value.match(/^(if|else|elseif|for|while|switch)$/)) {
value += " ";
nextToken.value = nextToken.value.trim();
// space before else, elseif
if (!breakBefore && token.type === "keyword" && value.trim().match(/^(else|elseif)$/)) {
code = code.trimRight();
value = " "+value;
}
// trim value after opening paren
} else if (token.type === "paren.lparen") {
nextToken.value = nextToken.value.trim();
// whitepace after {
if (value.substr(-1) === "{") {
code = code.replace(/ +$/, "");
value = value + " ";
}
// ensure curly brace is preceeded by whitespace
if (value.substr(0, 1) === "{" && !code.match(/\s$/))
value = " " + value;
// remove space before closing paren
} else if (token.type === "paren.rparen") {
code = code.replace(/ +$/, "");
// ensure curly brace is preceeded by whitespace
if (value.substr(0, 1) === "}" && !code.match(/\s$/))
value = " " + value;
// add spaces around conditional operators
} else if ((token.type === "keyword.operator" || token.type === "keyword") && value.match(/^(=|==|===|!=|!==|&&|\|\||and|or|xor|\+=|.=|>|>=|<|<=)$/)) {
code = code.trimRight();
value = " " + value + " ";
nextToken.value = nextToken.value.trim();
} else if (token.type === "support.php_tag" && value === "?>" && !breakBefore) {
code = code.trimRight();
value = " " + value;
}
// unindent if first paren is closing
if (curRow != row && rowTokens) {
abort = false;
for (i = 0; i<rowTokens.length && !abort; i++) {
if (rowTokens[i].type == "paren.rparen") {
indent--;
abort = true;
} else if (rowTokens[i].type == "paren.lparen")
abort = true;
}
}
// add indent to code
if (breakBefore && !is(token, "comment")) {
var count = indent;
if (inCase && !onCaseLine)
count++;
if (indentNextLine) {
count++;
indentNextLine = false;
}
for (i = 0; i < count; i++)
code += tabString;
}
// indent if there are last paren is opening
if (curRow != row && rowTokens) {
indentNextLine = null;
abort = false;
for (i = rowTokens.length-1; i>=0 && !abort; i--) {
if (rowTokens[i].type == "paren.rparen") {
abort = true;
} else if (rowTokens[i].type == "paren.lparen") {
indent++;
indentNextLine = false;
abort = true;
}
}
}
// indent one line after if or else
if (indentNextLine !== false && token.type === "keyword" && value.trim().match(/^(if|else|elseif|for|while)$/))
indentNextLine = true;
// add to code
code += value;
breakBefore = false;
// line break after opening block tag or doctype
if ((is(token, "tag-close") && (inBlock || blockTags.indexOf(tagName) !== -1)) || (is(token, "doctype") && value==">")) {
// undo linebreak if tag is immediately closed
if (inBlock && nextToken && nextToken.value === "</")
rowsToAdd--;
else
rowsToAdd++;
}
// indent after opening tag
if (is(token, "tag-open") && value === "<" && singletonTags.indexOf(nextToken.value) === -1)
indent++;
// remove indent if unknown singleton
if (is(token, "tag-name"))
tagName = value;
if (is(token, "tag-close") && value === "/>" && singletonTags.indexOf(tagName) === -1)
indent--;
row = curRow;
}
token = nextToken;
}
code = code.trim();
session.doc.setValue(code);
};
@ -54,4 +254,4 @@ exports.commands = [{
bindKey: "Ctrl-Shift-B"
}];
});
});

View File

@ -1,365 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2012, 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 TokenIterator = require("ace/token_iterator").TokenIterator;
exports.newLines = [{
type: 'support.php_tag',
value: '<?php'
}, {
type: 'support.php_tag',
value: '<?'
}, {
type: 'support.php_tag',
value: '?>'
}, {
type: 'paren.lparen',
value: '{',
indent: true
}, {
type: 'paren.rparen',
breakBefore: true,
value: '}',
indent: false
}, {
type: 'paren.rparen',
breakBefore: true,
value: '})',
indent: false,
dontBreak: true
}, {
type: 'comment'
}, {
type: 'text',
value: ';'
}, {
type: 'text',
value: ':',
context: 'php'
}, {
type: 'keyword',
value: 'case',
indent: true,
dontBreak: true
}, {
type: 'keyword',
value: 'default',
indent: true,
dontBreak: true
}, {
type: 'keyword',
value: 'break',
indent: false,
dontBreak: true
}, {
type: 'punctuation.doctype.end',
value: '>'
}, {
type: 'meta.tag.punctuation.end',
value: '>'
}, {
type: 'meta.tag.punctuation.begin',
value: '<',
blockTag: true,
indent: true,
dontBreak: true
}, {
type: 'meta.tag.punctuation.begin',
value: '</',
indent: false,
breakBefore: true,
dontBreak: true
}, {
type: 'punctuation.operator',
value: ';'
}];
exports.spaces = [{
type: 'xml-pe',
prepend: true
},{
type: 'entity.other.attribute-name',
prepend: true
}, {
type: 'storage.type',
value: 'var',
append: true
}, {
type: 'storage.type',
value: 'function',
append: true
}, {
type: 'keyword.operator',
value: '='
}, {
type: 'keyword',
value: 'as',
prepend: true,
append: true
}, {
type: 'keyword',
value: 'function',
append: true
}, {
type: 'support.function',
next: /[^\(]/,
append: true
}, {
type: 'keyword',
value: 'or',
append: true,
prepend: true
}, {
type: 'keyword',
value: 'and',
append: true,
prepend: true
}, {
type: 'keyword',
value: 'case',
append: true
}, {
type: 'keyword.operator',
value: '||',
append: true,
prepend: true
}, {
type: 'keyword.operator',
value: '&&',
append: true,
prepend: true
}];
exports.singleTags = ['!doctype','area','base','br','hr','input','img','link','meta'];
exports.transform = function(iterator, maxPos, context) {
var token = iterator.getCurrentToken();
var newLines = exports.newLines;
var spaces = exports.spaces;
var singleTags = exports.singleTags;
var code = '';
var indentation = 0;
var dontBreak = false;
var tag;
var lastTag;
var lastToken = {};
var nextTag;
var nextToken = {};
var breakAdded = false;
var value = '';
while (token!==null) {
if( !token ){
token = iterator.stepForward();
continue;
}
//change syntax
//php
if( token.type == 'support.php_tag' && token.value != '?>' ){
context = 'php';
}
else if( token.type == 'support.php_tag' && token.value == '?>' ){
context = 'html';
}
//css
else if( token.type == 'meta.tag.name.style' && context != 'css' ){
context = 'css';
}
else if( token.type == 'meta.tag.name.style' && context == 'css' ){
context = 'html';
}
//js
else if( token.type == 'meta.tag.name.script' && context != 'js' ){
context = 'js';
}
else if( token.type == 'meta.tag.name.script' && context == 'js' ){
context = 'html';
}
nextToken = iterator.stepForward();
//tag name
if (nextToken && nextToken.type.indexOf('meta.tag.name') == 0) {
nextTag = nextToken.value;
}
//don't linebreak
if ( lastToken.type == 'support.php_tag' && lastToken.value == '<?=') {
dontBreak = true;
}
//lowercase
if (token.type == 'meta.tag.name') {
token.value = token.value.toLowerCase();
}
//trim spaces
if (token.type == 'text') {
token.value = token.value.trim();
}
//skip empty tokens
if (!token.value) {
token = nextToken;
continue;
}
//put spaces back in
value = token.value;
for (var i in spaces) {
if (
token.type == spaces[i].type &&
(!spaces[i].value || token.value == spaces[i].value) &&
(
nextToken &&
(!spaces[i].next || spaces[i].next.test(nextToken.value))
)
) {
if (spaces[i].prepend) {
value = ' ' + token.value;
}
if (spaces[i].append) {
value += ' ';
}
}
}
//tag name
if (token.type.indexOf('meta.tag.name') == 0) {
tag = token.value;
//console.log(tag);
}
//new line before
breakAdded = false;
//outdent
for (i in newLines) {
if (
token.type == newLines[i].type &&
(
!newLines[i].value ||
token.value == newLines[i].value
) &&
(
!newLines[i].blockTag ||
singleTags.indexOf(nextTag) === -1
) &&
(
!newLines[i].context ||
newLines[i].context === context
)
) {
if (newLines[i].indent === false) {
indentation--;
}
if (
newLines[i].breakBefore &&
( !newLines[i].prev || newLines[i].prev.test(lastToken.value) )
) {
code += "\n";
breakAdded = true;
//indent
for (i = 0; i < indentation; i++) {
code += "\t";
}
}
break;
}
}
if (dontBreak===false) {
for (i in newLines) {
if (
lastToken.type == newLines[i].type &&
(
!newLines[i].value || lastToken.value == newLines[i].value
) &&
(
!newLines[i].blockTag ||
singleTags.indexOf(tag) === -1
) &&
(
!newLines[i].context ||
newLines[i].context === context
)
) {
if (newLines[i].indent === true) {
indentation++;
}
if (!newLines[i].dontBreak && !breakAdded) {
code += "\n";
//indent
for (i = 0; i < indentation; i++) {
code += "\t";
}
}
break;
}
}
}
code += value;
//linebreaks back on after end short php tag
if ( lastToken.type == 'support.php_tag' && lastToken.value == '?>' ) {
dontBreak = false;
}
//next token
lastTag = tag;
lastToken = token;
token = nextToken;
if (token===null) {
break;
}
}
return code;
};
});

252
plugins/node_modules/ace/lib/ace/ext/beautify_test.js generated vendored Normal file
View File

@ -0,0 +1,252 @@
if (typeof process !== "undefined") {
require("amd-loader");
}
define(function(require, exports, module) {
"use strict";
var assert = require("assert");
var EditSession = require("../edit_session").EditSession;
var beautify = require("./beautify");
var PHPMode = require("../mode/php").Mode;
// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite
module.exports = {
timeout: 10000,
"test beautify block tag indentation": function(next) {
var s = new EditSession([
"<div>",
"<h1>test</h1>",
"</div>"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<div>\n"
+ "\t<h1>test</h1>\n"
+ "</div>");
next();
},
"test beautify block tag line breaks and indentation": function(next) {
var s = new EditSession([
"<html><body><div></div></body></html>"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<html>\n"
+ "<body>\n"
+ "\t<div></div>\n"
+ "</body>\n"
+ "</html>");
next();
},
"test beautify empty block tag": function(next) {
var s = new EditSession([
"\t<div></div>"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<div></div>");
next();
},
"test beautify inline tag indentation": function(next) {
var s = new EditSession([
"<div>",
"<span>hello world</span>",
"</div>"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<div>\n"
+ "\t<span>hello world</span>\n"
+ "</div>");
next();
},
"test beautify multiline inline tag indentation": function(next) {
var s = new EditSession([
"<div>",
"<span>",
"hello world",
"</span>",
"</div>"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<div>\n"
+ "\t<span>\n"
+ "\t\thello world\n"
+ "\t</span>\n"
+ "</div>");
next();
},
"test beautify singleton tag indentation": function(next) {
var s = new EditSession([
"<div>",
"hello<br>",
"world",
"</div>"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<div>\n"
+ "\thello<br>\n"
+ "\tworld\n"
+ "</div>");
next();
},
"test beautify unknown singleton indentation": function(next) {
var s = new EditSession([
"<div>",
"hello<single />",
"world",
"</div>"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<div>\n"
+ "\thello<single />\n"
+ "\tworld\n"
+ "</div>");
next();
},
"test beautify curly indentation": function(next) {
var s = new EditSession([
"<?php",
"if (true) {",
"$i++;",
"}"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n"
+ "if (true) {\n"
+ "\t$i++;\n"
+ "}");
next();
},
"test beautify adding bracket whitespace": function(next) {
var s = new EditSession([
"<?php",
"if(true){",
"\t$i++;",
"}"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n"
+ "if (true) {\n"
+ "\t$i++;\n"
+ "}");
next();
},
"test beautify removing bracket whitespace": function(next) {
var s = new EditSession([
"<?php",
"if ( true ) {",
"\t$i++;",
"}"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n"
+ "if (true) {\n"
+ "\t$i++;\n"
+ "}");
next();
},
"test beautify adding keyword whitespace": function(next) {
var s = new EditSession([
"<?php",
"if ($foo===true) {",
"\t$i++;",
"}"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n"
+ "if ($foo === true) {\n"
+ "\t$i++;\n"
+ "}");
next();
},
"test beautify if without paren": function(next) {
var s = new EditSession([
"<?php",
"if ($foo===true)",
"$i++;",
"print $i"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n"
+ "if ($foo === true)\n"
+ "\t$i++;\n"
+ "print $i");
next();
},
"test beautify switch indentation": function(next) {
var s = new EditSession([
"<?php",
"switch ($i) {",
"case 1;",
"case 2;",
"print $i;",
"break;",
"}"
], new PHPMode());
s.setUseSoftTabs(false);
beautify.beautify(s);
assert.equal(s.getValue(), "<?php\n"
+ "switch ($i) {\n"
+ "\tcase 1;\n"
+ "\tcase 2;\n"
+ "\t\tprint $i;\n"
+ "\tbreak;\n"
+ "}");
next();
}
};
});
if (typeof module !== "undefined" && module === require.main) {
require("asyncjs").test.testcase(module.exports).exec();
}

View File

@ -1,979 +0,0 @@
define(function(require, exports, module) {
/* ChromeVox Ace namespace. */
var cvoxAce = {};
/* Typedefs for Closure compiler. */
/**
* @typedef {{
rate: number,
pitch: number,
volume: number,
relativePitch: number,
punctuationEcho: string
}}
*/
/* TODO(peterxiao): Export this typedef through cvox.Api. */
cvoxAce.SpeechProperty;
/**
* @typedef {{
* row: number,
* column: number
* }}
*/
cvoxAce.Cursor;
/**
* @typedef {{
type: string,
value: string
}}
}
*/
cvoxAce.Token;
/**
* These are errors and information that Ace will display in the gutter.
* @typedef {{
row: number,
column: number,
value: string
}}
}
*/
cvoxAce.Annotation;
/* Speech Properties. */
/**
* Speech property for speaking constant tokens.
* @type {cvoxAce.SpeechProperty}
*/
var CONSTANT_PROP = {
'rate': 0.8,
'pitch': 0.4,
'volume': 0.9
};
/**
* Default speech property for speaking tokens.
* @type {cvoxAce.SpeechProperty}
*/
var DEFAULT_PROP = {
'rate': 1,
'pitch': 0.5,
'volume': 0.9
};
/**
* Speech property for speaking entity tokens.
* @type {cvoxAce.SpeechProperty}
*/
var ENTITY_PROP = {
'rate': 0.8,
'pitch': 0.8,
'volume': 0.9
};
/**
* Speech property for speaking keywords.
* @type {cvoxAce.SpeechProperty}
*/
var KEYWORD_PROP = {
'rate': 0.8,
'pitch': 0.3,
'volume': 0.9
};
/**
* Speech property for speaking storage tokens.
* @type {cvoxAce.SpeechProperty}
*/
var STORAGE_PROP = {
'rate': 0.8,
'pitch': 0.7,
'volume': 0.9
};
/**
* Speech property for speaking variable tokens.
* @type {cvoxAce.SpeechProperty}
*/
var VARIABLE_PROP = {
'rate': 0.8,
'pitch': 0.8,
'volume': 0.9
};
/**
* Speech property for speaking deleted text.
* @type {cvoxAce.SpeechProperty}
*/
var DELETED_PROP = {
'punctuationEcho': 'none',
'relativePitch': -0.6
};
/* Constants for Earcons. */
var ERROR_EARCON = 'ALERT_NONMODAL';
var MODE_SWITCH_EARCON = 'ALERT_MODAL';
var NO_MATCH_EARCON = 'INVALID_KEYPRESS';
/* Constants for vim state. */
var INSERT_MODE_STATE = 'insertMode';
var COMMAND_MODE_STATE = 'start';
var REPLACE_LIST = [
{
substr: ';',
newSubstr: ' semicolon '
},
{
substr: ':',
newSubstr: ' colon '
}
];
/**
* Context menu commands.
*/
var Command = {
SPEAK_ANNOT: 'annots',
SPEAK_ALL_ANNOTS: 'all_annots',
TOGGLE_LOCATION: 'toggle_location',
SPEAK_MODE: 'mode',
SPEAK_ROW_COL: 'row_col',
TOGGLE_DISPLACEMENT: 'toggle_displacement',
FOCUS_TEXT: 'focus_text'
};
/**
* Key prefix for each shortcut.
*/
var KEY_PREFIX = 'CONTROL + SHIFT ';
/* Globals. */
cvoxAce.editor = null;
/**
* Last cursor position.
* @type {cvoxAce.Cursor}
*/
var lastCursor = null;
/**
* Table of annotations.
* @typedef {!Object.<number, Object<number, cvoxAce.Annotation>>}
*/
var annotTable = {};
/**
* Whether to speak character, word, and then line. This allows blind users
* to know the location of the cursor when they change lines.
* @typedef {boolean}
*/
var shouldSpeakRowLocation = false;
/**
* Whether to speak displacement.
* @typedef {boolean}
*/
var shouldSpeakDisplacement = false;
/**
* Whether text was changed to cause a cursor change event.
* @typedef {boolean}
*/
var changed = false;
/**
* Current state vim is in.
*/
var vimState = null;
/**
* Mapping from key code to shortcut.
*/
var keyCodeToShortcutMap = {};
/**
* Mapping from command to shortcut.
*/
var cmdToShortcutMap = {};
/**
* Get shortcut string from keyCode.
* @param {number} keyCode Key code of shortcut.
* @return {string} String representation of shortcut.
*/
var getKeyShortcutString = function(keyCode) {
return KEY_PREFIX + String.fromCharCode(keyCode);
};
/**
* Return if in vim mode.
* @return {boolean} True if in Vim mode.
*/
var isVimMode = function() {
var keyboardHandler = cvoxAce.editor.keyBinding.getKeyboardHandler();
return keyboardHandler.$id === 'ace/keyboard/vim';
};
/**
* Gets the current token.
* @param {!cvoxAce.Cursor} cursor Current position of the cursor.
* @return {!cvoxAce.Token} Token at the current position.
*/
var getCurrentToken = function(cursor) {
return cvoxAce.editor.getSession().getTokenAt(cursor.row, cursor.column + 1);
};
/**
* Gets the current line the cursor is under.
* @param {!cvoxAce.Cursor} cursor Current cursor position.
*/
var getCurrentLine = function(cursor) {
return cvoxAce.editor.getSession().getLine(cursor.row);
};
/**
* Event handler for row changes. When the user changes rows we want to speak
* the line so the user can work on this line. If shouldSpeakRowLocation is on
* then we speak the character, then the row, then the line so the user knows
* where the cursor is.
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
*/
var onRowChange = function(currCursor) {
/* Notify that this line has an annotation. */
if (annotTable[currCursor.row]) {
cvox.Api.playEarcon(ERROR_EARCON);
}
if (shouldSpeakRowLocation) {
cvox.Api.stop();
speakChar(currCursor);
speakTokenQueue(getCurrentToken(currCursor));
speakLine(currCursor.row, 1);
} else {
speakLine(currCursor.row, 0);
}
};
/**
* Returns whether the cursor is at the beginning of a word. A word is
* a grouping of alphanumeric characters including underscores.
* @param {!cvoxAce.Cursor} cursor Current cursor position.
* @return {boolean} Whether there is word.
*/
var isWord = function(cursor) {
var line = getCurrentLine(cursor);
var lineSuffix = line.substr(cursor.column - 1);
if (cursor.column === 0) {
lineSuffix = ' ' + line;
}
/* Use regex to tell if the suffix is at the start of a new word. */
var firstWordRegExp = /^\W(\w+)/;
var words = firstWordRegExp.exec(lineSuffix);
return words !== null;
};
/**
* A mapping of syntax type to speech properties / expanding rules.
*/
var rules = {
'constant': {
prop: CONSTANT_PROP
},
'entity': {
prop: ENTITY_PROP
},
'keyword': {
prop: KEYWORD_PROP
},
'storage': {
prop: STORAGE_PROP
},
'variable': {
prop: VARIABLE_PROP
},
'meta': {
prop: DEFAULT_PROP,
replace: [
{
substr: '</',
newSubstr: ' closing tag '
},
{
substr: '/>',
newSubstr: ' close tag '
},
{
substr: '<',
newSubstr: ' tag start '
},
{
substr: '>',
newSubstr: ' tag end '
}
]
}
};
/**
* Default rule to be used.
*/
var DEFAULT_RULE = {
prop: DEFAULT_RULE
};
/**
* Expands substrings to how they are read based on the given rules.
* @param {string} value Text to be expanded.
* @param {Array.<Object>} replaceRules Rules to determine expansion.
* @return {string} New expanded value.
*/
var expand = function(value, replaceRules) {
var newValue = value;
for (var i = 0; i < replaceRules.length; i++) {
var replaceRule = replaceRules[i];
var regexp = new RegExp(replaceRule.substr, 'g');
newValue = newValue.replace(regexp, replaceRule.newSubstr);
}
return newValue;
};
/**
* Merges tokens from start inclusive to end exclusive.
* @param {Array.<cvoxAce.Token>} Tokens to be merged.
* @param {number} start Start index inclusive.
* @param {number} end End index exclusive.
* @return {cvoxAce.Token} Merged token.
*/
var mergeTokens = function(tokens, start, end) {
/* Different type of token found! Merge all previous like tokens. */
var newToken = {};
newToken.value = '';
newToken.type = tokens[start].type;
for (var j = start; j < end; j++) {
newToken.value += tokens[j].value;
}
return newToken;
};
/**
* Merges tokens that use the same speech properties.
* @param {Array.<cvoxAce.Token>} tokens Tokens to be merged.
* @return {Array.<cvoxAce.Token>} Merged tokens.
*/
var mergeLikeTokens = function(tokens) {
if (tokens.length <= 1) {
return tokens;
}
var newTokens = [];
var lastLikeIndex = 0;
for (var i = 1; i < tokens.length; i++) {
var lastLikeToken = tokens[lastLikeIndex];
var currToken = tokens[i];
if (getTokenRule(lastLikeToken) !== getTokenRule(currToken)) {
newTokens.push(mergeTokens(tokens, lastLikeIndex, i));
lastLikeIndex = i;
}
}
newTokens.push(mergeTokens(tokens, lastLikeIndex, tokens.length));
return newTokens;
};
/**
* Returns if given row is a whitespace row.
* @param {number} row Row.
* @return {boolean} True if row is whitespaces.
*/
var isRowWhiteSpace = function(row) {
var line = cvoxAce.editor.getSession().getLine(row);
var whiteSpaceRegexp = /^\s*$/;
return whiteSpaceRegexp.exec(line) !== null;
};
/**
* Speak the line with syntax properties.
* @param {number} row Row to speak.
* @param {number} queue Queue mode to speak.
*/
var speakLine = function(row, queue) {
var tokens = cvoxAce.editor.getSession().getTokens(row);
if (tokens.length === 0 || isRowWhiteSpace(row)) {
cvox.Api.playEarcon('EDITABLE_TEXT');
return;
}
tokens = mergeLikeTokens(tokens);
var firstToken = tokens[0];
/* Filter out first token. */
tokens = tokens.filter(function(token) {
return token !== firstToken;
});
/* Speak first token separately to flush if queue. */
speakToken_(firstToken, queue);
/* Speak rest of tokens. */
tokens.forEach(speakTokenQueue);
};
/**
* Speak the token based on the syntax of the token, flushing.
* @param {!cvoxAce.Token} token Token to speak.
* @param {number} queue Queue mode.
*/
var speakTokenFlush = function(token) {
speakToken_(token, 0);
};
/**
* Speak the token based on the syntax of the token, queueing.
* @param {!cvoxAce.Token} token Token to speak.
* @param {number} queue Queue mode.
*/
var speakTokenQueue = function(token) {
speakToken_(token, 1);
};
/**
* @param {!cvoxAce.Token} token Token to speak.
* Get the token speech property.
*/
var getTokenRule = function(token) {
/* Types are period delimited. In this case, we only syntax speak the outer
* most type of token. */
if (!token || !token.type) {
return;
}
var split = token.type.split('.');
if (split.length === 0) {
return;
}
var type = split[0];
var rule = rules[type];
if (!rule) {
return DEFAULT_RULE;
}
return rule;
};
/**
* Speak the token based on the syntax of the token.
* @private
* @param {!cvoxAce.Token} token Token to speak.
* @param {number} queue Queue mode.
*/
var speakToken_ = function(token, queue) {
var rule = getTokenRule(token);
var value = expand(token.value, REPLACE_LIST);
if (rule.replace) {
value = expand(value, rule.replace);
}
cvox.Api.speak(value, queue, rule.prop);
};
/**
* Speaks the character under the cursor. This is queued.
* @param {!cvoxAce.Cursor} cursor Current cursor position.
* @return {string} Character.
*/
var speakChar = function(cursor) {
var line = getCurrentLine(cursor);
cvox.Api.speak(line[cursor.column], 1);
};
/**
* Speaks the jump from lastCursor to currCursor. This function assumes the
* jump takes place on the current line.
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
*/
var speakDisplacement = function(lastCursor, currCursor) {
var line = getCurrentLine(currCursor);
/* Get the text that we jumped past. */
var displace = line.substring(lastCursor.column, currCursor.column);
/* Speak out loud spaces. */
displace = displace.replace(/ /g, ' space ');
cvox.Api.speak(displace);
};
/**
* Speaks the word if the cursor jumped to a new word or to the beginning
* of the line. Otherwise speak the charactor.
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
*/
var speakCharOrWordOrLine = function(lastCursor, currCursor) {
/* Say word only if jump. */
if (Math.abs(lastCursor.column - currCursor.column) !== 1) {
var currLineLength = getCurrentLine(currCursor).length;
/* Speak line if jumping to beginning or end of line. */
if (currCursor.column === 0 || currCursor.column === currLineLength) {
speakLine(currCursor.row, 0);
return;
}
if (isWord(currCursor)) {
cvox.Api.stop();
speakTokenQueue(getCurrentToken(currCursor));
return;
}
}
speakChar(currCursor);
};
/**
* Event handler for column changes. If shouldSpeakDisplacement is on, then
* we just speak displacements in row changes. Otherwise, we either speak
* the character for single character movements, the word when jumping to the
* next word, or the entire line if jumping to beginning or end of the line.
* @param {!cvoxAce.Cursor} lastCursor Previous cursor position.
* @param {!cvoxAce.Cursor} currCursor Current cursor position.
*/
var onColumnChange = function(lastCursor, currCursor) {
if (!cvoxAce.editor.selection.isEmpty()) {
speakDisplacement(lastCursor, currCursor);
cvox.Api.speak('selected', 1);
}
else if (shouldSpeakDisplacement) {
speakDisplacement(lastCursor, currCursor);
} else {
speakCharOrWordOrLine(lastCursor, currCursor);
}
};
/**
* Event handler for cursor changes. Classify cursor changes as either row or
* column changes, then delegate accordingly.
* @param {!Event} evt The event.
*/
var onCursorChange = function(evt) {
/* Do not speak if cursor change was a result of text insertion. We want to
* speak the text that was inserted and not where the cursor lands. */
if (changed) {
changed = false;
return;
}
var currCursor = cvoxAce.editor.selection.getCursor();
if (currCursor.row !== lastCursor.row) {
onRowChange(currCursor);
} else {
onColumnChange(lastCursor, currCursor);
}
lastCursor = currCursor;
};
/**
* Event handler for selection changes.
* @param {!Event} evt The event.
*/
var onSelectionChange = function(evt) {
/* Assumes that when selection changes to empty, the user has unselected. */
if (cvoxAce.editor.selection.isEmpty()) {
cvox.Api.speak('unselected');
}
};
/**
* Event handler for source changes. We want auditory feedback for inserting
* and deleting text.
* @param {!Event} evt The event.
*/
var onChange = function(delta) {
switch (delta.action) {
case 'remove':
cvox.Api.speak(delta.text, 0, DELETED_PROP);
/* Let the future cursor change event know it's from text change. */
changed = true;
break;
case 'insert':
cvox.Api.speak(delta.text, 0);
/* Let the future cursor change event know it's from text change. */
changed = true;
break;
}
};
/**
* Returns whether or not the annotation is new.
* @param {!cvoxAce.Annotation} annot Annotation in question.
* @return {boolean} Whether annot is new.
*/
var isNewAnnotation = function(annot) {
var row = annot.row;
var col = annot.column;
return !annotTable[row] || !annotTable[row][col];
};
/**
* Populates the annotation table.
* @param {!Array.<cvoxAce.Annotation>} annotations Array of annotations.
*/
var populateAnnotations = function(annotations) {
annotTable = {};
for (var i = 0; i < annotations.length; i++) {
var annotation = annotations[i];
var row = annotation.row;
var col = annotation.column;
if (!annotTable[row]) {
annotTable[row] = {};
}
annotTable[row][col] = annotation;
}
};
/**
* Event handler for annotation changes. We want to notify the user when an
* a new annotation appears.
* @param {!Event} evt Event.
*/
var onAnnotationChange = function(evt) {
var annotations = cvoxAce.editor.getSession().getAnnotations();
var newAnnotations = annotations.filter(isNewAnnotation);
if (newAnnotations.length > 0) {
cvox.Api.playEarcon(ERROR_EARCON);
}
populateAnnotations(annotations);
};
/**
* Speak annotation.
* @param {!cvoxAce.Annotation} annot Annotation to speak.
*/
var speakAnnot = function(annot) {
var annotText = annot.type + ' ' + annot.text + ' on ' +
rowColToString(annot.row, annot.column);
annotText = annotText.replace(';', 'semicolon');
cvox.Api.speak(annotText, 1);
};
/**
* Speak annotations in a row.
* @param {number} row Row of annotations to speak.
*/
var speakAnnotsByRow = function(row) {
var annots = annotTable[row];
for (var col in annots) {
speakAnnot(annots[col]);
}
};
/**
* Get a string representation of a row and column.
* @param {boolean} row Zero indexed row.
* @param {boolean} col Zero indexed column.
* @return {string} Row and column to be spoken.
*/
var rowColToString = function(row, col) {
return 'row ' + (row + 1) + ' column ' + (col + 1);
};
/**
* Speaks the row and column.
*/
var speakCurrRowAndCol = function() {
cvox.Api.speak(rowColToString(lastCursor.row, lastCursor.column));
};
/**
* Speaks all annotations.
*/
var speakAllAnnots = function() {
for (var row in annotTable) {
speakAnnotsByRow(row);
}
};
/**
* Speak the vim mode. If no vim mode, this function does nothing.
*/
var speakMode = function() {
if (!isVimMode()) {
return;
}
switch (cvoxAce.editor.keyBinding.$data.state) {
case INSERT_MODE_STATE:
cvox.Api.speak('Insert mode');
break;
case COMMAND_MODE_STATE:
cvox.Api.speak('Command mode');
break;
}
};
/**
* Toggle speak location.
*/
var toggleSpeakRowLocation = function() {
shouldSpeakRowLocation = !shouldSpeakRowLocation;
/* Auditory feedback of the change. */
if (shouldSpeakRowLocation) {
cvox.Api.speak('Speak location on row change enabled.');
} else {
cvox.Api.speak('Speak location on row change disabled.');
}
};
/**
* Toggle speak displacement.
*/
var toggleSpeakDisplacement = function() {
shouldSpeakDisplacement = !shouldSpeakDisplacement;
/* Auditory feedback of the change. */
if (shouldSpeakDisplacement) {
cvox.Api.speak('Speak displacement on column changes.');
} else {
cvox.Api.speak('Speak current character or word on column changes.');
}
};
/**
* Event handler for key down events. Gets the right shortcut from the map,
* and calls the associated function.
* @param {!Event} evt Keyboard event.
*/
var onKeyDown = function(evt) {
if (evt.ctrlKey && evt.shiftKey) {
var shortcut = keyCodeToShortcutMap[evt.keyCode];
if (shortcut) {
shortcut.func();
}
}
};
/**
* Event handler for status change events. Auditory feedback of changing
* between vim states.
* @param {!Event} evt Change status event.
* @param {!Object} editor Editor state.
*/
var onChangeStatus = function(evt, editor) {
if (!isVimMode()) {
return;
}
var state = editor.keyBinding.$data.state;
if (state === vimState) {
/* State hasn't changed, do nothing. */
return;
}
switch (state) {
case INSERT_MODE_STATE:
cvox.Api.playEarcon(MODE_SWITCH_EARCON);
/* When in insert mode, we want to speak out keys as feedback. */
cvox.Api.setKeyEcho(true);
break;
case COMMAND_MODE_STATE:
cvox.Api.playEarcon(MODE_SWITCH_EARCON);
/* When in command mode, we want don't speak out keys because those keys
* are not being inserted in the document. */
cvox.Api.setKeyEcho(false);
break;
}
vimState = state;
};
/**
* Handles context menu events. This is a ChromeVox feature where hitting
* the shortcut ChromeVox + comma will open up a search bar where you can
* type in various commands. All keyboard shortcuts are also commands that
* can be invoked. This handles the event that ChromeVox sends to the page.
* @param {Event} evt Event received.
*/
var contextMenuHandler = function(evt) {
var cmd = evt.detail['customCommand'];
var shortcut = cmdToShortcutMap[cmd];
if (shortcut) {
shortcut.func();
/* ChromeVox will bring focus to an element near the cursor instead of the
* text input. */
cvoxAce.editor.focus();
}
};
/**
* Initialize the ChromeVox context menu.
*/
var initContextMenu = function() {
var ACTIONS = SHORTCUTS.map(function(shortcut) {
return {
desc: shortcut.desc + getKeyShortcutString(shortcut.keyCode),
cmd: shortcut.cmd
};
});
/* Attach ContextMenuActions. */
var body = document.querySelector('body');
body.setAttribute('contextMenuActions', JSON.stringify(ACTIONS));
/* Listen for ContextMenu events. */
body.addEventListener('ATCustomEvent', contextMenuHandler, true);
};
/**
* Event handler for find events. When there is a match, we want to speak the
* line we are now at. Otherwise, we want to notify the user there was no
* match
* @param {!Event} evt The event.
*/
var onFindSearchbox = function(evt) {
if (evt.match) {
/* There is still a match! Speak the line. */
speakLine(lastCursor.row, 0);
} else {
/* No match, give auditory feedback! */
cvox.Api.playEarcon(NO_MATCH_EARCON);
}
};
/**
* Focus to text input.
*/
var focus = function() {
cvoxAce.editor.focus();
};
/**
* Shortcut definitions.
*/
var SHORTCUTS = [
{
/* 1 key. */
keyCode: 49,
func: function() {
speakAnnotsByRow(lastCursor.row);
},
cmd: Command.SPEAK_ANNOT,
desc: 'Speak annotations on line'
},
{
/* 2 key. */
keyCode: 50,
func: speakAllAnnots,
cmd: Command.SPEAK_ALL_ANNOTS,
desc: 'Speak all annotations'
},
{
/* 3 key. */
keyCode: 51,
func: speakMode,
cmd: Command.SPEAK_MODE,
desc: 'Speak Vim mode'
},
{
/* 4 key. */
keyCode: 52,
func: toggleSpeakRowLocation,
cmd: Command.TOGGLE_LOCATION,
desc: 'Toggle speak row location'
},
{
/* 5 key. */
keyCode: 53,
func: speakCurrRowAndCol,
cmd: Command.SPEAK_ROW_COL,
desc: 'Speak row and column'
},
{
/* 6 key. */
keyCode: 54,
func: toggleSpeakDisplacement,
cmd: Command.TOGGLE_DISPLACEMENT,
desc: 'Toggle speak displacement'
},
{
/* 7 key. */
keyCode: 55,
func: focus,
cmd: Command.FOCUS_TEXT,
desc: 'Focus text'
}
];
/**
* Event handler for focus events.
*/
var onFocus = function(_, editor) {
cvoxAce.editor = editor;
/* Set up listeners. */
editor.getSession().selection.on('changeCursor', onCursorChange);
editor.getSession().selection.on('changeSelection', onSelectionChange);
editor.getSession().on('change', onChange);
editor.getSession().on('changeAnnotation', onAnnotationChange);
editor.on('changeStatus', onChangeStatus);
editor.on('findSearchBox', onFindSearchbox);
editor.container.addEventListener('keydown', onKeyDown);
lastCursor = editor.selection.getCursor();
};
/**
* Initialize the theme.
* @param {Object} editor Editor to use.
*/
var init = function(editor) {
onFocus(null, editor);
/* Construct maps. */
SHORTCUTS.forEach(function(shortcut) {
keyCodeToShortcutMap[shortcut.keyCode] = shortcut;
cmdToShortcutMap[shortcut.cmd] = shortcut;
});
editor.on('focus', onFocus);
/* Assume we start in command mode if vim. */
if (isVimMode()) {
cvox.Api.setKeyEcho(false);
}
initContextMenu();
};
/**
* Returns if cvox exists, and the api exists.
* @return {boolean} Whether not Cvox Api exists.
*/
function cvoxApiExists() {
return (typeof(cvox) !== 'undefined') && cvox && cvox.Api;
}
/**
* Number of tries for Cvox loading.
* @type {number}
*/
var tries = 0;
/**
* Max number of tries to watch for Cvox loading.
* @type {number}
*/
var MAX_TRIES = 15;
/**
* Check for ChromeVox load.
* @param {Object} editor Editor to use.
*/
function watchForCvoxLoad(editor) {
if (cvoxApiExists()) {
init(editor);
} else {
tries++;
if (tries >= MAX_TRIES) {
return;
}
window.setTimeout(watchForCvoxLoad, 500, editor);
}
}
var Editor = require('../editor').Editor;
require('../config').defineOptions(Editor.prototype, 'editor', {
enableChromevoxEnhancements: {
set: function(val) {
if (val) {
watchForCvoxLoad(this);
}
},
value: true // turn it on by default or check for window.cvox
}
});
});

View File

@ -1,109 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
* All rights reserved.
*
* Contributed to Ajax.org under the BSD license.
*
* 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 ***** */
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
/*global define, require */
/**
* Add Editor Menu Options
* @fileOverview Add Editor Menu Options <br />
* The menu options property needs to be added to the editor
* so that the settings menu can know about options for
* selection elements and track which option is selected.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
define(function(require, exports, module) {
'use strict';
/**
* The menu options property needs to be added to the editor
* so that the settings menu can know about options for
* selection elements and track which option is selected.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {ace.Editor} editor An instance of the ace editor.
*/
module.exports.addEditorMenuOptions = function addEditorMenuOptions (editor) {
var modelist = require('../modelist');
var themelist = require('../themelist');
editor.menuOptions = {
setNewLineMode: [{
textContent: "unix",
value: "unix"
}, {
textContent: "windows",
value: "windows"
}, {
textContent: "auto",
value: "auto"
}],
setTheme: [],
setMode: [],
setKeyboardHandler: [{
textContent: "ace",
value: ""
}, {
textContent: "vim",
value: "ace/keyboard/vim"
}, {
textContent: "emacs",
value: "ace/keyboard/emacs"
}, {
textContent: "textarea",
value: "ace/keyboard/textarea"
}, {
textContent: "sublime",
value: "ace/keyboard/sublime"
}]
};
editor.menuOptions.setTheme = themelist.themes.map(function(theme) {
return {
textContent: theme.caption,
value: theme.theme
};
});
editor.menuOptions.setMode = modelist.modes.map(function(mode) {
return {
textContent: mode.name,
value: mode.mode
};
});
};
});

View File

@ -1,148 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
* All rights reserved.
*
* Contributed to Ajax.org under the BSD license.
*
* 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 ***** */
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
/*global define, require */
/**
* Element Generator
* @fileOverview Element Generator <br />
* Contains methods for generating elements.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
define(function(require, exports, module) {
'use strict';
/**
* Creates a DOM option element
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {object} obj An object containing properties to add to the dom
* element. If one of those properties is named `selected` then it will be
* added as an attribute on the element instead.
*/
module.exports.createOption = function createOption (obj) {
var attribute;
var el = document.createElement('option');
for(attribute in obj) {
if(obj.hasOwnProperty(attribute)) {
if(attribute === 'selected') {
el.setAttribute(attribute, obj[attribute]);
} else {
el[attribute] = obj[attribute];
}
}
}
return el;
};
/**
* Creates a DOM checkbox element.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {string} id The id of the element.
* @param {boolean} checked Whether or not the element is checked.
* @param {string} clss The class of the element.
* @returns {DOMElement} Returns a checkbox element reference.
*/
module.exports.createCheckbox = function createCheckbox (id, checked, clss) {
var el = document.createElement('input');
el.setAttribute('type', 'checkbox');
el.setAttribute('id', id);
el.setAttribute('name', id);
el.setAttribute('value', checked);
el.setAttribute('class', clss);
if(checked) {
el.setAttribute('checked', 'checked');
}
return el;
};
/**
* Creates a DOM text input element.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {string} id The id of the element.
* @param {string} value The default value of the input element.
* @param {string} clss The class of the element.
* @returns {DOMElement} Returns an input element reference.
*/
module.exports.createInput = function createInput (id, value, clss) {
var el = document.createElement('input');
el.setAttribute('type', 'text');
el.setAttribute('id', id);
el.setAttribute('name', id);
el.setAttribute('value', value);
el.setAttribute('class', clss);
return el;
};
/**
* Creates a DOM label element.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {string} text The label text.
* @param {string} labelFor The id of the element being labeled.
* @returns {DOMElement} Returns a label element reference.
*/
module.exports.createLabel = function createLabel (text, labelFor) {
var el = document.createElement('label');
el.setAttribute('for', labelFor);
el.textContent = text;
return el;
};
/**
* Creates a DOM selection element.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {string} id The id of the element.
* @param {string} values An array of objects suitable for `createOption`
* @param {string} clss The class of the element.
* @returns {DOMElement} Returns a selection element reference.
* @see ace/ext/element_generator.createOption
*/
module.exports.createSelection = function createSelection (id, values, clss) {
var el = document.createElement('select');
el.setAttribute('id', id);
el.setAttribute('name', id);
el.setAttribute('class', clss);
values.forEach(function(item) {
el.appendChild(module.exports.createOption(item));
});
return el;
};
});

View File

@ -1,264 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
* All rights reserved.
*
* Contributed to Ajax.org under the BSD license.
*
* 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 ***** */
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/
/*global define*/
/**
* Generates the settings menu
* @fileOverview Generates the settings menu.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
define(function(require, exports, module) {
'use strict';
var egen = require('./element_generator');
var addEditorMenuOptions = require('./add_editor_menu_options').addEditorMenuOptions;
var getSetFunctions = require('./get_set_functions').getSetFunctions;
/**
* Generates an interactive menu with settings useful to end users.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {ace.Editor} editor An instance of the ace editor.
*/
module.exports.generateSettingsMenu = function generateSettingsMenu (editor) {
/**
* container for dom elements that will go in the menu.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
var elements = [];
/**
* Sorts the menu entries (elements var) so they'll appear in alphabetical order
* the sort is performed based on the value of the contains property
* of each element. Since this is an `array.sort` the array is sorted
* in place.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
function cleanupElementsList() {
elements.sort(function(a, b) {
var x = a.getAttribute('contains');
var y = b.getAttribute('contains');
return x.localeCompare(y);
});
}
/**
* Wraps all dom elements contained in the elements var with a single
* div.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
function wrapElements() {
var topmenu = document.createElement('div');
topmenu.setAttribute('id', 'ace_settingsmenu');
elements.forEach(function(element) {
topmenu.appendChild(element);
});
var el = topmenu.appendChild(document.createElement('div'));
var version = require("../../ace").version;
el.style.padding = "1em";
el.textContent = "Ace version " + version;
return topmenu;
}
/**
* Creates a new menu entry.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {object} obj This is a reference to the object containing the
* set function. It is used to set up event listeners for when the
* menu options change.
* @param {string} clss Maps to the class of the dom element. This is
* the name of the object containing the set function e.g. `editor`,
* `session`, `renderer`.
* @param {string} item This is the set function name. It maps to the
* id of the dom element (check, select, input) and to the "contains"
* attribute of the div holding both the element and its label.
* @param {mixed} val This is the value of the setting. It is mapped to
* the dom element's value, checked, or selected option accordingly.
*/
function createNewEntry(obj, clss, item, val) {
var el;
var div = document.createElement('div');
div.setAttribute('contains', item);
div.setAttribute('class', 'ace_optionsMenuEntry');
div.setAttribute('style', 'clear: both;');
div.appendChild(egen.createLabel(
item.replace(/^set/, '').replace(/([A-Z])/g, ' $1').trim(),
item
));
if (Array.isArray(val)) {
el = egen.createSelection(item, val, clss);
el.addEventListener('change', function(e) {
try{
editor.menuOptions[e.target.id].forEach(function(x) {
if(x.textContent !== e.target.textContent) {
delete x.selected;
}
});
obj[e.target.id](e.target.value);
} catch (err) {
throw new Error(err);
}
});
} else if(typeof val === 'boolean') {
el = egen.createCheckbox(item, val, clss);
el.addEventListener('change', function(e) {
try{
// renderer['setHighlightGutterLine'](true);
obj[e.target.id](!!e.target.checked);
} catch (err) {
throw new Error(err);
}
});
} else {
// this aids in giving the ability to specify settings through
// post and get requests.
// /ace_editor.html?setMode=ace/mode/html&setOverwrite=true
el = egen.createInput(item, val, clss);
el.addEventListener('change', function(e) {
try{
if(e.target.value === 'true') {
obj[e.target.id](true);
} else if(e.target.value === 'false') {
obj[e.target.id](false);
} else {
obj[e.target.id](e.target.value);
}
} catch (err) {
throw new Error(err);
}
});
}
el.style.cssText = 'float:right;';
div.appendChild(el);
return div;
}
/**
* Generates selection fields for the menu and populates their options
* using information from `editor.menuOptions`
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {string} item The set function name.
* @param {object} esr A reference to the object having the set function.
* @param {string} clss The name of the object containing the set function.
* @param {string} fn The matching get function's function name.
* @returns {DOMElement} Returns a dom element containing a selection
* element populated with options. The option whose value matches that
* returned from `esr[fn]()` will be selected.
*/
function makeDropdown(item, esr, clss, fn) {
var val = editor.menuOptions[item];
var currentVal = esr[fn]();
if (typeof currentVal == 'object')
currentVal = currentVal.$id;
val.forEach(function(valuex) {
if (valuex.value === currentVal)
valuex.selected = 'selected';
});
return createNewEntry(esr, clss, item, val);
}
/**
* Processes the set functions returned from `getSetFunctions`. First it
* checks for menu options defined in `editor.menuOptions`. If no
* options are specified then it checks whether there is a get function
* (replace set with get) for the setting. When either of those
* conditions are met it will attempt to create a new entry for the
* settings menu and push it into the elements array defined above.
* It can only do so for get functions which return
* strings, numbers, and booleans. A special case is written in for
* `getMode` where it looks at the returned objects `$id` property and
* forwards that through instead. Other special cases could be written
* in but that would get a bit ridiculous.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {object} setObj An item from the array returned by
* `getSetFunctions`.
*/
function handleSet(setObj) {
var item = setObj.functionName;
var esr = setObj.parentObj;
var clss = setObj.parentName;
var val;
var fn = item.replace(/^set/, 'get');
if(editor.menuOptions[item] !== undefined) {
// has options for select element
elements.push(makeDropdown(item, esr, clss, fn));
} else if(typeof esr[fn] === 'function') {
// has get function
try {
val = esr[fn]();
if(typeof val === 'object') {
// setMode takes a string, getMode returns an object
// the $id property of that object is the string
// which may be given to setMode...
val = val.$id;
}
// the rest of the get functions return strings,
// booleans, or numbers.
elements.push(
createNewEntry(esr, clss, item, val)
);
} catch (e) {
// if there are errors it is because the element
// does not belong in the settings menu
}
}
}
addEditorMenuOptions(editor);
// gather the set functions
getSetFunctions(editor).forEach(function(setObj) {
// populate the elements array with good stuff.
handleSet(setObj);
});
// sort the menu entries in the elements list so people can find
// the settings in alphabetical order.
cleanupElementsList();
// dump the entries from the elements list and wrap them up in a div
return wrapElements();
};
});

View File

@ -1,141 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2013 Matthew Christopher Kastor-Inare III, Atropa Inc. Intl
* All rights reserved.
*
* Contributed to Ajax.org under the BSD license.
*
* 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 ***** */
/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true */
/*global define*/
/**
* Get Set Functions
* @fileOverview Get Set Functions <br />
* Gets various functions for setting settings.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
define(function(require, exports, module) {
'use strict';
/**
* Generates a list of set functions for the settings menu.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
* @param {object} editor The editor instance
* @return {array} Returns an array of objects. Each object contains the
* following properties: functionName, parentObj, and parentName. The
* function name will be the name of a method beginning with the string
* `set` which was found. The parent object will be a reference to the
* object having the method matching the function name. The parent name
* will be a string representing the identifier of the parent object e.g.
* `editor`, `session`, or `renderer`.
*/
module.exports.getSetFunctions = function getSetFunctions (editor) {
/**
* Output array. Will hold the objects described above.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
var out = [];
/**
* This object provides a map between the objects which will be
* traversed and the parent name which will appear in the output.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
var my = {
'editor' : editor,
'session' : editor.session,
'renderer' : editor.renderer
};
/**
* This array will hold the set function names which have already been
* found so that they are not added to the output multiple times.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
var opts = [];
/**
* This is a list of set functions which will not appear in the settings
* menu. I don't know what to do with setKeyboardHandler. When I tried
* to use it, it didn't appear to be working. Someone who knows better
* could remove it from this list and add it's options to
* add_editor_menu_options.js
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
var skip = [
'setOption',
'setUndoManager',
'setDocument',
'setValue',
'setBreakpoints',
'setScrollTop',
'setScrollLeft',
'setSelectionStyle',
'setWrapLimitRange'
];
/**
* This will search the objects mapped to the `my` variable above. When
* it finds a set function in the object that is not listed in the
* `skip` list or the `opts` list it will push a new object to the
* output array.
* @author <a href="mailto:matthewkastor@gmail.com">
* Matthew Christopher Kastor-Inare III </a><br />
* Hial Atropa!!
*/
['renderer', 'session', 'editor'].forEach(function(esra) {
var esr = my[esra];
var clss = esra;
for(var fn in esr) {
if(skip.indexOf(fn) === -1) {
if(/^set/.test(fn) && opts.indexOf(fn) === -1) {
// found set function
opts.push(fn);
out.push({
'functionName' : fn,
'parentObj' : esr,
'parentName' : clss
});
}
}
}
});
return out;
};
});

View File

@ -21,7 +21,6 @@
.ace_optionsMenuEntry:hover {
background-color: rgba(100, 100, 100, 0.1);
-webkit-transition: all 0.5s;
transition: all 0.3s
}
@ -33,7 +32,7 @@
position: absolute;
right: -8px;
top: -8px;
z-index: 1000;
z-index: 100000;
}
.ace_closeButton{
background: rgba(245, 146, 146, 0.9);
@ -45,4 +44,21 @@
.ace_optionsMenuCommand {
color: darkcyan;
font-weight: normal;
}
.ace_optionsMenuEntry input, .ace_optionsMenuEntry button {
vertical-align: middle;
}
.ace_optionsMenuEntry button[ace_selected_button=true] {
background: #e7e7e7;
box-shadow: 1px 0px 2px 0px #adadad inset;
border-color: #adadad;
}
.ace_optionsMenuEntry button {
background: white;
border: 1px solid lightgray;
margin: 0px;
}
.ace_optionsMenuEntry button:hover{
background: #f0f0f0;
}

View File

@ -72,6 +72,7 @@ var supportedModes = {
Dockerfile: ["^Dockerfile"],
Dot: ["dot"],
Drools: ["drl"],
Edifact: ["edi"],
Eiffel: ["e|ge"],
EJS: ["ejs"],
Elixir: ["ex|exs"],

331
plugins/node_modules/ace/lib/ace/ext/options.js generated vendored Normal file
View File

@ -0,0 +1,331 @@
define(function(require, exports, module) {
"use strict";
var overlayPage = require('./menu_tools/overlay_page').overlayPage;
var dom = require("../lib/dom");
var oop = require("../lib/oop");
var EventEmitter = require("../lib/event_emitter").EventEmitter;
var buildDom = dom.buildDom;
var modelist = require("./modelist");
var themelist = require("./themelist");
var themes = { Bright: [], Dark: [] };
themelist.themes.forEach(function(x) {
themes[x.isDark ? "Dark" : "Bright"].push({ caption: x.caption, value: x.theme });
});
var modes = modelist.modes.map(function(x){
return { caption: x.caption, value: x.mode };
});
var optionGroups = {
Main: {
Mode: {
path: "mode",
type: "select",
items: modes
},
Theme: {
path: "theme",
type: "select",
items: themes
},
"Keybinding": {
type: "buttonBar",
path: "keyboardHandler",
items: [
{ caption : "Ace", value : null },
{ caption : "Vim", value : "ace/keyboard/vim" },
{ caption : "Emacs", value : "ace/keyboard/emacs" }
// { caption : "Sublime", value : "ace/keyboard/sublime" }
]
},
"Font Size": {
path: "fontSize",
type: "number",
defaultValue: 12,
defaults: [
{caption: "12px", value: 12},
{caption: "24px", value: 24}
]
},
"Soft Wrap": {
type: "buttonBar",
path: "wrap",
items: [
{ caption : "Off", value : "off" },
{ caption : "Free", value : "free" },
{ caption : "80", value : "80" },
{ caption : "40", value : "40" }
]
},
"Cursor Style": {
path: "cursorStyle",
items: [
{ caption : "Ace", value : "ace" },
{ caption : "Slim", value : "slim" },
{ caption : "Smooth", value : "smooth" },
{ caption : "Smooth And Slim", value : "smooth slim" },
{ caption : "Wide", value : "wide" }
]
},
"Folding": {
path: "foldStyle",
items: [
{ caption : "Manual", value : "manual" },
{ caption : "Mark begin", value : "markbegin" },
{ caption : "Mark begin and end", value : "markbeginend" }
]
},
"Soft Tabs": [{
path: "useSoftTabs"
}, {
path: "tabSize",
type: "number",
values: [2, 3, 4, 8, 16]
}],
"Overscroll": {
type: "buttonBar",
path: "scrollPastEnd",
items: [
{ caption : "None", value : 0 },
{ caption : "Half", value : 0.5 },
{ caption : "Full", value : 1 }
]
}
},
More: {
"Atomic soft tabs": {
path: "navigateWithinSoftTabs"
},
"Enable Behaviours": {
path: "behavioursEnabled"
},
"Full Line Selection": {
type: "checkbox",
values: "text|line",
path: "selectionStyle"
},
"Highlight Active Line": {
path: "highlightActiveLine"
},
"Show Invisibles": {
path: "showInvisibles"
},
"Show Indent Guides": {
path: "displayIndentGuides"
},
"Persistent Scrollbar": [{
path: "hScrollBarAlwaysVisible"
}, {
path: "vScrollBarAlwaysVisible"
}],
"Animate scrolling": {
path: "animatedScroll"
},
"Show Gutter": {
path: "showGutter"
},
"Show Print Margin": [{
path: "showPrintMargin"
}, {
type: "number",
path: "printMarginColumn"
}],
"Highlight selected word": {
path: "highlightSelectedWord"
},
"Fade Fold Widgets": {
path: "fadeFoldWidgets"
},
"Merge Undo Deltas": {
path: "mergeUndoDeltas",
items: [
{ caption : "Always", value : "always" },
{ caption : "Never", value : "false" },
{ caption : "Timed", value : "true" }
]
},
"Elastic Tabstops": {
path: "useElasticTabstops"
},
"Incremental Search": {
path: "useIncrementalSearch"
},
"Read-only": {
path: "readOnly"
},
"Copy without selection": {
path: "copyWithEmptySelection"
},
"Live Autocompletion": {
path: "enableLiveAutocompletion"
}
}
};
var OptionPanel = function(editor, element) {
this.editor = editor;
this.container = element || document.createElement("div");
this.groups = [];
this.options = {};
};
(function() {
oop.implement(this, EventEmitter);
this.add = function(config) {
if (config.Main)
oop.mixin(optionGroups.Main, config.Main);
if (config.More)
oop.mixin(optionGroups.More, config.More);
};
this.render = function() {
this.container.innerHTML = "";
buildDom(["table", {id: "controls"},
this.renderOptionGroup(optionGroups.Main),
["tr", null, ["td", {colspan: 2},
["table", {id: "more-controls"},
this.renderOptionGroup(optionGroups.More)
]
]]
], this.container);
};
this.renderOptionGroup = function(group) {
return Object.keys(group).map(function(key, i) {
var item = group[key];
if (!item.position)
item.position = i / 10000;
if (!item.label)
item.label = key;
return item;
}).sort(function(a, b) {
return a.position - b.position;
}).map(function(item) {
return this.renderOption(item.label, item);
}, this);
};
this.renderOptionControl = function(key, option) {
var self = this;
if (Array.isArray(option)) {
return option.map(function(x) {
return self.renderOptionControl(key, x);
});
}
var control;
var value = self.getOption(option);
if (option.values && option.type != "checkbox") {
if (typeof option.values == "string")
option.values = option.values.split("|");
option.items = option.values.map(function(v) {
return { value: v, name: v };
});
}
if (option.type == "buttonBar") {
control = ["div", option.items.map(function(item) {
return ["button", {
value: item.value,
ace_selected_button: value == item.value,
onclick: function() {
self.setOption(option, item.value);
var nodes = this.parentNode.querySelectorAll("[ace_selected_button]");
for (var i = 0; i < nodes.length; i++) {
nodes[i].removeAttribute("ace_selected_button");
}
this.setAttribute("ace_selected_button", true);
}
}, item.desc || item.caption || item.name];
})];
} else if (option.type == "number") {
control = ["input", {type: "number", value: value || option.defaultValue, style:"width:3em", oninput: function() {
self.setOption(option, parseInt(this.value));
}}];
if (option.defaults) {
control = [control, option.defaults.map(function(item) {
return ["button", {onclick: function() {
var input = this.parentNode.firstChild;
input.value = item.value;
input.oninput();
}}, item.caption];
})];
}
} else if (option.items) {
var buildItems = function(items) {
return items.map(function(item) {
return ["option", { value: item.value || item.name }, item.desc || item.caption || item.name];
});
};
var items = Array.isArray(option.items)
? buildItems(option.items)
: Object.keys(option.items).map(function(key) {
return ["optgroup", {"label": key}, buildItems(option.items[key])];
});
control = ["select", { id: key, value: value, onchange: function() {
self.setOption(option, this.value);
} }, items];
} else {
if (typeof option.values == "string")
option.values = option.values.split("|");
if (option.values) value = value == option.values[1];
control = ["input", { type: "checkbox", id: key, checked: value || null, onchange: function() {
var value = this.checked;
if (option.values) value = option.values[value ? 1 : 0];
self.setOption(option, value);
}}];
if (option.type == "checkedNumber") {
control = [control, []];
}
}
return control;
};
this.renderOption = function(key, option) {
if (option.path && !option.onchange && !this.editor.$options[option.path])
return;
this.options[option.path] = option;
var safeKey = "-" + option.path;
var control = this.renderOptionControl(safeKey, option);
return ["tr", {class: "ace_optionsMenuEntry"}, ["td",
["label", {for: safeKey}, key]
], ["td", control]];
};
this.setOption = function(option, value) {
if (typeof option == "string")
option = this.options[option];
if (value == "false") value = false;
if (value == "true") value = true;
if (value == "null") value = null;
if (value == "undefined") value = undefined;
if (typeof value == "string" && parseFloat(value).toString() == value)
value = parseFloat(value);
if (option.onchange)
option.onchange(value);
else
this.editor.setOption(option.path, value);
this._signal("setOption", {name: option.path, value: value});
};
this.getOption = function(option) {
if (option.getValue)
return option.getValue();
return this.editor.getOption(option.path);
};
}).call(OptionPanel.prototype);
exports.OptionPanel = OptionPanel;
});

View File

@ -45,7 +45,7 @@
define(function(require, exports, module) {
"use strict";
var generateSettingsMenu = require('./menu_tools/generate_settings_menu').generateSettingsMenu;
var OptionPanel = require("ace/ext/options").OptionPanel;
var overlayPage = require('./menu_tools/overlay_page').overlayPage;
/**
* This displays the settings menu if it is not already being shown.
@ -55,10 +55,14 @@ var overlayPage = require('./menu_tools/overlay_page').overlayPage;
* @param {ace.Editor} editor An instance of the ace editor.
*/
function showSettingsMenu(editor) {
// make sure the menu isn't open already.
var sm = document.getElementById('ace_settingsmenu');
if (!sm)
overlayPage(editor, generateSettingsMenu(editor), '0', '0', '0');
// show if the menu isn't open already.
if (!document.getElementById('ace_settingsmenu')) {
var options = new OptionPanel(editor);
options.render();
options.container.id = "ace_settingsmenu";
overlayPage(editor, options.container, '0', '0', '0');
options.container.querySelector("select,input,button,checkbox").focus();
}
}
/**

View File

@ -182,12 +182,9 @@ exports.transformTextarea = function(element, options) {
position: "absolute",
right: "0px",
bottom: "0px",
background: "red",
cursor: "nw-resize",
borderStyle: "solid",
borderWidth: "9px 8px 10px 9px",
width: "2px",
borderColor: "lightblue gray gray lightblue",
border: "solid 9px",
borderColor: "lightblue gray gray #ceade6",
zIndex: 101
});
@ -246,6 +243,7 @@ exports.transformTextarea = function(element, options) {
});
event.addListener(settingOpener, "mousedown", function(e) {
e.preventDefault();
if (state == "toggle") {
editor.setDisplaySettings();
return;

View File

@ -62,6 +62,7 @@ var themeData = [
["Ambiance" ,"ambiance" , "dark"],
["Chaos" ,"chaos" , "dark"],
["Clouds Midnight" ,"clouds_midnight" , "dark"],
["Dracula" ,"" , "dark"],
["Cobalt" ,"cobalt" , "dark"],
["Gruvbox" ,"gruvbox" , "dark"],
["Green on Black" ,"gob" , "dark"],

View File

@ -36,19 +36,6 @@ require("../incremental_search");
var iSearchCommandModule = require("../commands/incremental_search_commands");
var screenToTextBlockCoordinates = function(x, y) {
var canvasPos = this.scroller.getBoundingClientRect();
var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding;
var col = Math.floor(offsetX / this.characterWidth);
var row = Math.floor(
(y + this.scrollTop - canvasPos.top) / this.lineHeight
);
return this.session.screenToDocumentPosition(row, col, offsetX);
};
var HashHandler = require("./hash_handler").HashHandler;
exports.handler = new HashHandler();
@ -143,7 +130,7 @@ exports.handler.attach = function(editor) {
editor.on("click", $resetMarkMode);
editor.on("changeSession", $kbSessionChange);
editor.renderer.screenToTextCoordinates = screenToTextBlockCoordinates;
editor.renderer.$blockCursor = true;
editor.setStyle("emacs-mode");
editor.commands.addCommands(commands);
exports.handler.platform = editor.commands.platform;
@ -153,7 +140,7 @@ exports.handler.attach = function(editor) {
};
exports.handler.detach = function(editor) {
delete editor.renderer.screenToTextCoordinates;
editor.renderer.$blockCursor = false;
editor.session.$selectLongWords = $formerLongWords;
editor.session.$useEmacsStyleLineStart = $formerLineStart;
editor.removeEventListener("click", $resetMarkMode);
@ -404,8 +391,8 @@ exports.emacsKeys = {
"Return|C-m": {command: "insertstring", args: "\n"}, // "newline"
"C-o": "splitline",
"M-d|C-Delete|Esc d": {command: "killWord", args: "right"},
"C-Backspace|M-Backspace|M-Delete|Esc Backspace": {command: "killWord", args: "left"},
"M-d|C-Delete": {command: "killWord", args: "right"},
"C-Backspace|M-Backspace|M-Delete": {command: "killWord", args: "left"},
"C-k": "killLine",
"C-y|S-Delete": "yank",

View File

@ -55,7 +55,9 @@ var TextInput = function(parentNode, host) {
text.style.opacity = "0";
parentNode.insertBefore(text, parentNode.firstChild);
var PLACEHOLDER = "\u2028\u2028";
// \x01 is displayed on firefox and with \u2028 textarea cursor is visible on ie
var PLACEHOLDER = useragent.isIE ? "\x01\x01" : "\u2028\u2028";
var PLACEHOLDER_RE = useragent.isIE ? /\x01/g : /\u2028/g;
var copied = false;
var pasted = false;
@ -64,6 +66,8 @@ var TextInput = function(parentNode, host) {
var isSelectionEmpty = true;
var copyWithEmptySelection = false;
var commandMode = false;
// FOCUS
// ie9 throws error if document.activeElement is accessed too soon
try { var isFocused = document.activeElement === text; } catch(e) {}
@ -88,10 +92,13 @@ var TextInput = function(parentNode, host) {
var ancestors = [];
if (isTransformed) {
var t = text.parentElement;
while (t) {
while (t && t.nodeType == 1) {
ancestors.push(t);
t.setAttribute("ace_nocontext", true);
t = t.parentElement;
if (!t.parentElement && t.getRootNode)
t = t.getRootNode().host;
else
t = t.parentElement;
}
}
text.focus({ preventScroll: true });
@ -347,7 +354,7 @@ var TextInput = function(parentNode, host) {
// console.log("onCompositionUpdate", inComposition && JSON.stringify(text.value))
if (!inComposition || !host.onCompositionUpdate || host.$readOnly)
return;
var val = text.value.replace(/\u2028/g, "");
var val = text.value.replace(PLACEHOLDER_RE, "");
if (inComposition.lastValue === val) return;
host.onCompositionUpdate(val);
@ -372,7 +379,7 @@ var TextInput = function(parentNode, host) {
inComposition = false;
var timer = setTimeout(function() {
timer = null;
var str = text.value.replace(/\u2028/g, "");
var str = text.value.replace(PLACEHOLDER_RE, "");
// console.log(str, c.lastValue)
if (inComposition)
return;
@ -387,7 +394,7 @@ var TextInput = function(parentNode, host) {
// console.log("onCompositionEnd", str, c.lastValue)
if (timer)
clearTimeout(timer);
str = str.replace(/\u2028/g, "");
str = str.replace(PLACEHOLDER_RE, "");
if (str == c.lastValue)
return "";
if (c.lastValue && timer)
@ -423,8 +430,14 @@ var TextInput = function(parentNode, host) {
return text;
};
this.setCommandMode = function(value) {
commandMode = value;
text.readOnly = false;
};
this.setReadOnly = function(readOnly) {
text.readOnly = readOnly;
if (!commandMode)
text.readOnly = readOnly;
};
this.setCopyWithEmptySelection = function(value) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -38,6 +38,7 @@ var EventEmitter = require("../lib/event_emitter").EventEmitter;
var CHAR_COUNT = 256;
var USE_OBSERVER = typeof ResizeObserver == "function";
var L = 200;
var FontMetrics = exports.FontMetrics = function(parentEl) {
this.el = dom.createElement("div");
@ -163,6 +164,70 @@ var FontMetrics = exports.FontMetrics = function(parentEl) {
this.el.parentNode.removeChild(this.el);
};
this.$getZoom = function getZoom(element) {
if (!element) return 1;
return (window.getComputedStyle(element).zoom || 1) * getZoom(element.parentElement);
};
this.$initTransformMeasureNodes = function() {
var t = function(t, l) {
return ["div", {
style: "position: absolute;top:" + t + "px;left:" + l + "px;"
}];
};
this.els = dom.buildDom([t(0, 0), t(L, 0), t(0, L), t(L, L)], this.el);
};
// general transforms from element coordinates x to screen coordinates u have the form
// | m1[0] m2[0] t[0] | | x | | u |
// | m1[1] m2[1] t[1] | . | y | == k | v |
// | h[0] h[1] 1 | | 1 | | 1 |
// this function finds the coeeficients of the matrix using positions of four points
//
this.transformCoordinates = function(clientPos, elPos) {
if (clientPos) {
var zoom = this.$getZoom(this.el);
clientPos = mul(1 / zoom, clientPos);
}
function solve(l1, l2, r) {
var det = l1[1] * l2[0] - l1[0] * l2[1];
return [
(-l2[1] * r[0] + l2[0] * r[1]) / det,
(+l1[1] * r[0] - l1[0] * r[1]) / det
];
}
function sub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
function add(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
function mul(a, b) { return [a * b[0], a * b[1]]; }
if (!this.els)
this.$initTransformMeasureNodes();
function p(el) {
var r = el.getBoundingClientRect();
return [r.left, r.top];
}
var a = p(this.els[0]);
var b = p(this.els[1]);
var c = p(this.els[2]);
var d = p(this.els[3]);
var h = solve(sub(d, b), sub(d, c), sub(add(b, c), add(d, a)));
var m1 = mul(1 + h[0], sub(b, a));
var m2 = mul(1 + h[1], sub(c, a));
if (elPos) {
var x = elPos;
var k = h[0] * x[0] / L + h[1] * x[1] / L + 1;
var ut = add(mul(x[0], m1), mul(x[1], m2));
return add(mul(1 / k / L, ut), a);
}
var u = sub(clientPos, a);
var f = solve(sub(m1, mul(h[0], u)), sub(m2, mul(h[1], u)), u);
return mul(L, f);
};
}).call(FontMetrics.prototype);
});

View File

@ -265,7 +265,6 @@ var Text = function(parentEl) {
// beeing folded.
this.$renderLine(html, row, false, row == foldStart ? foldLine : false);
// don't use setInnerHtml since we are working with an empty DIV
container.innerHTML = html.join("");
if (this.$useLineGroups()) {
container.className = 'ace_line_group';

View File

@ -33,6 +33,51 @@ define(function(require, exports, module) {
var XHTML_NS = "http://www.w3.org/1999/xhtml";
exports.buildDom = function buildDom(arr, parent, refs) {
if (typeof arr == "string" && arr) {
var txt = document.createTextNode(arr);
if (parent)
parent.appendChild(txt);
return txt;
}
if (!Array.isArray(arr))
return arr;
if (typeof arr[0] != "string" || !arr[0]) {
var els = [];
for (var i = 0; i < arr.length; i++) {
var ch = buildDom(arr[i], parent, refs);
ch && els.push(ch);
}
return els;
}
var el = document.createElement(arr[0]);
var options = arr[1];
var childIndex = 1;
if (options && typeof options == "object" && !Array.isArray(options))
childIndex = 2;
for (var i = childIndex; i < arr.length; i++)
buildDom(arr[i], el, refs);
if (childIndex == 2) {
Object.keys(options).forEach(function(n) {
var val = options[n];
if (n === "class") {
el.className = Array.isArray(val) ? val.join(" ") : val;
} else if (typeof val == "function" || n == "value") {
el[n] = val;
} else if (n === "ref") {
if (refs) refs[val] = el;
} else if (val != null) {
el.setAttribute(n, val);
}
});
}
if (parent)
parent.appendChild(el);
return el;
};
exports.getDocumentHead = function(doc) {
if (!doc)
doc = document;
@ -107,70 +152,35 @@ exports.setCssClass = function(node, className, include) {
exports.hasCssString = function(id, doc) {
var index = 0, sheets;
doc = doc || document;
if (doc.createStyleSheet && (sheets = doc.styleSheets)) {
if ((sheets = doc.querySelectorAll("style"))) {
while (index < sheets.length)
if (sheets[index++].owningElement.id === id) return true;
} else if ((sheets = doc.getElementsByTagName("style"))) {
while (index < sheets.length)
if (sheets[index++].id === id) return true;
if (sheets[index++].id === id)
return true;
}
return false;
};
exports.importCssString = function importCssString(cssText, id, doc) {
doc = doc || document;
// If style is already imported return immediately.
if (id && exports.hasCssString(id, doc))
return null;
exports.importCssString = function importCssString(cssText, id, container) {
var root = container && container.getRootNode
? container.getRootNode()
: container || document;
var style;
var doc = root.ownerDocument || root;
// If style is already imported return immediately.
if (id && exports.hasCssString(id, root))
return null;
if (id)
cssText += "\n/*# sourceURL=ace/css/" + id + " */";
if (doc.createStyleSheet) {
style = doc.createStyleSheet();
style.cssText = cssText;
if (id)
style.owningElement.id = id;
} else {
style = exports.createElement("style");
style.appendChild(doc.createTextNode(cssText));
if (id)
style.id = id;
var style = exports.createElement("style");
style.appendChild(doc.createTextNode(cssText));
if (id)
style.id = id;
exports.getDocumentHead(doc).appendChild(style);
}
};
exports.importCssStylsheet = function(uri, doc) {
if (doc.createStyleSheet) {
doc.createStyleSheet(uri);
} else {
var link = exports.createElement('link');
link.rel = 'stylesheet';
link.href = uri;
exports.getDocumentHead(doc).appendChild(link);
}
};
exports.getInnerWidth = function(element) {
return (
parseInt(exports.computedStyle(element, "paddingLeft"), 10) +
parseInt(exports.computedStyle(element, "paddingRight"), 10) +
element.clientWidth
);
};
exports.getInnerHeight = function(element) {
return (
parseInt(exports.computedStyle(element, "paddingTop"), 10) +
parseInt(exports.computedStyle(element, "paddingBottom"), 10) +
element.clientHeight
);
if (root == doc)
root = exports.getDocumentHead(doc);
root.appendChild(style);
};
exports.scrollbarWidth = function(document) {
@ -212,75 +222,10 @@ exports.scrollbarWidth = function(document) {
if (typeof document == "undefined") {
exports.importCssString = function() {};
return;
}
if (window.pageYOffset !== undefined) {
exports.getPageScrollTop = function() {
return window.pageYOffset;
};
exports.getPageScrollLeft = function() {
return window.pageXOffset;
};
}
else {
exports.getPageScrollTop = function() {
return document.body.scrollTop;
};
exports.getPageScrollLeft = function() {
return document.body.scrollLeft;
};
}
if (window.getComputedStyle)
exports.computedStyle = function(element, style) {
if (style)
return (window.getComputedStyle(element, "") || {})[style] || "";
return window.getComputedStyle(element, "") || {};
};
else
exports.computedStyle = function(element, style) {
if (style)
return element.currentStyle[style];
return element.currentStyle;
};
/*
* Optimized set innerHTML. This is faster than plain innerHTML if the element
* already contains a lot of child elements.
*
* See http://blog.stevenlevithan.com/archives/faster-than-innerhtml for details
*/
exports.setInnerHtml = function(el, innerHtml) {
var element = el.cloneNode(false);//document.createElement("div");
element.innerHTML = innerHtml;
el.parentNode.replaceChild(element, el);
return element;
};
if ("textContent" in document.documentElement) {
exports.setInnerText = function(el, innerText) {
el.textContent = innerText;
};
exports.getInnerText = function(el) {
return el.textContent;
};
}
else {
exports.setInnerText = function(el, innerText) {
el.innerText = innerText;
};
exports.getInnerText = function(el) {
return el.innerText;
};
}
exports.getParentWindow = function(document) {
return document.defaultView || document.parentWindow;
exports.computedStyle = function(element, style) {
return window.getComputedStyle(element, "") || {};
};
});

View File

@ -34,6 +34,8 @@ function checkModes() {
console.warn("missing comment in " + modeName);
if (!m.$id)
console.warn("missing id in " + modeName);
if (!m.$behaviour)
console.warn("missing behavior in " + modeName);
var tokenizer = (new Mode).getTokenizer();
testComments(m.lineCommentStart, testLineComment, tokenizer, modeName);

View File

@ -1,16 +1,17 @@
test: header 1
#f
# f
test: header 2
## foo
test: header ends with ' #'
# # #
test: header ends with '#'
#foo#
# foo#
test: 6+ #s is not a valid header
####### foo
test: # followed be only space is not a valid header
test: # followed be only space is a valid header
#
test: only space between #s is not a valid header
test: only space between #s is a valid header
# #
# test links [Cloud9 IDE](http://www.c9.io/) #

View File

@ -1,10 +1,13 @@
[[
"start",
["text.xml","test: header 1 "]
],[
"start",
["text.xml","#f"]
],[
"start",
["markup.heading.1","#"],
["heading","f"]
["heading"," f"]
],[
"start",
["text.xml","test: header 2"]
@ -25,7 +28,7 @@
],[
"start",
["markup.heading.1","#"],
["heading","foo# "]
["heading"," foo# "]
],[
"start",
["text.xml","test: 6+ #s is not a valid header"]
@ -34,16 +37,18 @@
["text.xml","####### foo"]
],[
"start",
["text.xml","test: # followed be only space is not a valid header"]
["text.xml","test: # followed be only space is a valid header"]
],[
"start",
["text.xml","# "]
["markup.heading.1","#"],
["heading"," "]
],[
"start",
["text.xml","test: only space between #s is not a valid header"]
["text.xml","test: only space between #s is a valid header"]
],[
"start",
["text.xml","# #"]
["markup.heading.1","#"],
["heading"," #"]
],[
"allowBlock"
],[
@ -111,4 +116,4 @@
"allowBlock"
],[
"allowBlock"
]]
]]

View File

@ -483,7 +483,11 @@
["text","name$"]
],[
"start",
["text"," nocheck editor "],
["text"," "],
["keyword","nocheck"],
["text"," "],
["keyword","editor"],
["text"," "],
["string.interpolated","'editor_name$'"]
],[
"start",
@ -493,7 +497,10 @@
["keyword","Close"]
],[
"start",
["text"," nocheck endeditor"]
["text"," "],
["keyword","nocheck"],
["text"," "],
["keyword","endeditor"]
],[
"start",
["text"," "]

View File

@ -110,4 +110,60 @@
["text","["],
["identifier","bufreadaddr"],
["text","];"]
],[
"start"
],[
"start",
["keyword","module"],
["text"," "],
["identifier","test"],
["text",";"]
],[
"start",
["text"," "],
["keyword","assign"],
["text"," "],
["identifier","a"],
["text"," "],
["keyword.operator","="],
["text"," "],
["string.start","\""],
["string","1"],
["string.end","\""],
["text",";"]
],[
"start",
["text"," "],
["keyword","initial"],
["text"," "],
["keyword","begin"]
],[
"string.start",
["text"," "],
["identifier","$display"],
["paren.lparen","("],
["string.start","\""],
["string","Hello "],
["constant.language.escape","\\77"],
["string","8"],
["constant.language.escape","\\xaa\\"]
],[
"start",
["string"," "],
["constant.language.escape","\\n"],
["string"," world"],
["string.end","\""],
["paren.rparen",")"]
],[
"start",
["text"," "],
["identifier","$finish"],
["text",";"]
],[
"start",
["text"," "],
["keyword","end"]
],[
"start",
["keyword","endmodule"]
]]

View File

@ -49,9 +49,9 @@ var Mode = function() {
oop.inherits(Mode, TextMode);
(function() {
this.lineCommentStart = ";";
this.lineCommentStart = [";", "#"];
this.$id = "ace/mode/assembly_x86";
}).call(Mode.prototype);
exports.Mode = Mode;
});
});

View File

@ -40,11 +40,14 @@ require("../../multi_select");
var assert = require("../../test/assertions");
var Range = require("../../range").Range;
var Editor = require("../../editor").Editor;
var UndoManager = require("../../undomanager").UndoManager;
var EditSession = require("../../edit_session").EditSession;
var MockRenderer = require("../../test/mockrenderer").MockRenderer;
var JavaScriptMode = require("../javascript").Mode;
var RustMode = require("../rust").Mode;
var XMLMode = require("../xml").Mode;
var HTMLMode = require("../html").Mode;
var CSSMode = require("../css").Mode;
var editor;
var exec = function(name, times, args) {
do {
@ -158,6 +161,7 @@ module.exports = {
},
"test: xml": function() {
editor = new Editor(new MockRenderer());
editor.session.setUndoManager(new UndoManager());
editor.setValue(["<OuterTag>",
" <SelfClosingTag />"
].join("\n"));
@ -198,6 +202,89 @@ module.exports = {
" > ",
"'> >"
].join("\n"));
editor.setValue("");
"<div x='1'>".split("").forEach(function(ch) {
exec("insertstring", 1, ch);
});
assert.equal(editor.getValue(), "<div x='1'></div>");
exec("insertstring", 1, ">");
assert.equal(editor.getValue(), "<div x='1'>></div>");
editor.setValue("<div '", 1);
exec("selectleft", 1);
exec("insertstring", 1, '"');
assert.equal(editor.getValue(), "<div \"");
exec("selectleft", 1);
exec("insertstring", 1, "'");
assert.equal(editor.getValue(), "<div '");
exec("selectleft", 1);
exec("insertstring", 1, "a");
exec("selectleft", 1);
exec("insertstring", 1, "'");
assert.equal(editor.getValue(), "<div 'a'");
},
"test: html": function() {
editor.session.setMode(new HTMLMode);
editor.setWrapBehavioursEnabled(false);
editor.setValue("<div a", 1);
exec("selectleft", 1);
exec("insertstring", 1, "'");
assert.equal(editor.getValue(), "<div '");
editor.setWrapBehavioursEnabled(true);
editor.setValue("<div a", 1);
exec("selectleft", 1);
exec("insertstring", 1, "'");
assert.equal(editor.getValue(), "<div 'a'");
editor.setValue("<div a=></div>", 1);
exec("gotoleft", 7);
exec("insertstring", 1, '"');
assert.equal(editor.getValue(), "<div a=\"\"></div>");
exec("insertstring", 1, '"');
exec("gotoright", 1);
exec("insertstring", 1, "\n");
assert.equal(editor.getValue(), "<div a=\"\">\n \n</div>");
exec("undo", 1);
assert.equal(editor.getValue(), "<div a=\"\"></div>");
exec("gotoleft", 1);
exec("backspace", 1);
assert.equal(editor.getValue(), "<div a=\"></div>");
exec("undo", 1);
exec("gotoleft", 1);
exec("backspace", 1);
assert.equal(editor.getValue(), "<div a=></div>");
exec("backspace", 1);
assert.equal(editor.getValue(), "<div a></div>");
editor.setValue(" <div><div>", 1);
editor.selection.moveTo(0, 9);
exec("insertstring", 1, "\n");
assert.equal(editor.getValue(), " <div>\n <div>");
editor.setValue(" <div></div>", 1);
exec("insertstring", 1, "\n");
assert.equal(editor.getValue(), " <div></div>\n ");
editor.setValue(" <br><br>", 1);
editor.selection.moveTo(0, 8);
exec("insertstring", 1, "\n");
assert.equal(editor.getValue(), " <br>\n <br>");
editor.setValue("<div a='x", 1);
exec("gotoleft", 1);
exec("insertstring", 1, ">");
assert.equal(editor.getValue(), "<div a='>x");
editor.setValue("");
"<!DOCTYPE html></div><link><a>".split("").forEach(function(ch) {
exec("insertstring", 1, ch);
});
assert.equal(editor.getValue(), "<!DOCTYPE html></div><link><a></a>");
},
"test: quotes": function() {
editor = new Editor(new MockRenderer());
@ -222,7 +309,80 @@ module.exports = {
exec("insertstring", 1, '`');
exec("insertstring", 1, 'b');
assert.equal(editor.getValue(), "`b`");
},
"test: css": function() {
editor.session.setMode(new CSSMode());
editor.setWrapBehavioursEnabled(true);
editor.setValue("a {padding", 1);
exec("insertstring", 1, ":");
assert.equal(editor.getValue(), "a {padding:;");
editor.setValue("a {padding:", 1);
exec("gotoleft", 1);
exec("insertstring", 1, ":");
assert.equal(editor.getValue(), "a {padding:");
editor.setValue("a {padding ", 1);
exec("insertstring", 1, ":");
assert.equal(editor.getValue(), "a {padding :;");
editor.setValue("a", 1);
exec("insertstring", 1, ":");
assert.equal(editor.getValue(), "a:");
editor.setValue("a {padding", 1);
exec("insertstring", 1, ":");
exec("backspace", 1);
assert.equal(editor.getValue(), "a {padding");
exec("backspace", 2);
exec("insertstring", 1, ":;");
exec("gotoleft", 1);
exec("backspace", 1);
assert.equal(editor.getValue(), "a {paddi;");
editor.setValue("a {padding :", 1);
exec("backspace", 1);
assert.equal(editor.getValue(), "a {padding ");
editor.setValue("a {padding:", 1);
exec("insertstring", 1, ";");
assert.equal(editor.getValue(), "a {padding:;");
editor.setValue(";", 1);
exec("gotoleft", 1);
exec("insertstring", 1, "a {padding");
exec("insertstring", 1, ":");
assert.equal(editor.getValue(), "a {padding:;");
editor.setValue(";", 1);
exec("selectleft", 1);
exec("insertstring", 1, ";");
assert.equal(editor.getValue(), ";");
editor.setValue("a {padding:;", 1);
exec("gotoleft", 1);
exec("insertstring", 1, ";");
assert.equal(editor.getValue(), "a {padding:;");
editor.setValue("a {padding:10px", 1);
exec("insertstring", 1, "!");
assert.equal(editor.getValue(), "a {padding:10px!important");
exec("removewordleft", 2);
exec("insertstring", 1, "}");
exec("gotoleft", 1);
exec("insertstring", 1, "!");
assert.equal(editor.getValue(), "a {padding:10px!important}");
exec("removewordleft", 2);
exec("insertstring", 1, ";");
exec("gotoleft", 1);
exec("insertstring", 1, "!");
assert.equal(editor.getValue(), "a {padding:10px!important;}");
editor.selection.moveTo(0, 3);
exec("insertstring", 1, "!");
assert.equal(editor.getValue(), "a {!padding:10px!important;}");
}
};
});

View File

@ -41,7 +41,7 @@ var CssBehaviour = function () {
this.inherit(CstyleBehaviour);
this.add("colon", "insertion", function (state, action, editor, session, text) {
if (text === ':') {
if (text === ':' && editor.selection.isEmpty()) {
var cursor = editor.getCursorPosition();
var iterator = new TokenIterator(session, cursor.row, cursor.column);
var token = iterator.getCurrentToken();
@ -57,7 +57,7 @@ var CssBehaviour = function () {
selection: [1, 1]
};
}
if (!line.substring(cursor.column).match(/^\s*;/)) {
if (/^(\s+[^;]|\s*$)/.test(line.substring(cursor.column))) {
return {
text: ':;',
selection: [1, 1]
@ -88,7 +88,7 @@ var CssBehaviour = function () {
});
this.add("semicolon", "insertion", function (state, action, editor, session, text) {
if (text === ';') {
if (text === ';' && editor.selection.isEmpty()) {
var cursor = editor.getCursorPosition();
var line = session.doc.getLine(cursor.row);
var rightChar = line.substring(cursor.column, cursor.column + 1);
@ -101,6 +101,20 @@ var CssBehaviour = function () {
}
});
this.add("!important", "insertion", function (state, action, editor, session, text) {
if (text === '!' && editor.selection.isEmpty()) {
var cursor = editor.getCursorPosition();
var line = session.doc.getLine(cursor.row);
if (/^\s*(;|}|$)/.test(line.substring(cursor.column))) {
return {
text: '!important',
selection: [10, 10]
};
}
}
});
};
oop.inherits(CssBehaviour, CstyleBehaviour);

View File

@ -37,7 +37,7 @@ var TokenIterator = require("../../token_iterator").TokenIterator;
var lang = require("../../lib/lang");
function is(token, type) {
return token.type.lastIndexOf(type + ".xml") > -1;
return token && token.type.lastIndexOf(type + ".xml") > -1;
}
var XmlBehaviour = function () {
@ -116,7 +116,9 @@ var XmlBehaviour = function () {
if (position.column < tokenEndColumn)
return;
if (position.column == tokenEndColumn) {
if (is(iterator.stepForward(), "attribute-value"))
var nextToken = iterator.stepForward();
// TODO also handle non-closed string at the end of the line
if (nextToken && is(nextToken, "attribute-value"))
return;
iterator.stepBackward();
}

View File

@ -28,7 +28,7 @@ var c_cppHighlightRules = function() {
);
var keywordOperators = (
"and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq" +
"and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|typeid|xor|xor_eq|" +
"const_cast|dynamic_cast|reinterpret_cast|static_cast|sizeof|namespace"
);

View File

@ -36,7 +36,7 @@ var TextMode = require("./text").Mode;
var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var WorkerClient = require("../worker/worker_client").WorkerClient;
// var CssCompletions = require("./css_completions").CssCompletions;
var CssCompletions = require("./css_completions").CssCompletions;
var CssBehaviour = require("./behaviour/css").CssBehaviour;
var CStyleFoldMode = require("./folding/cstyle").FoldMode;
@ -44,7 +44,7 @@ var Mode = function() {
this.HighlightRules = CssHighlightRules;
this.$outdent = new MatchingBraceOutdent();
this.$behaviour = new CssBehaviour();
// this.$completer = new CssCompletions();
this.$completer = new CssCompletions();
this.foldingRules = new CStyleFoldMode();
};
oop.inherits(Mode, TextMode);

View File

@ -3929,8 +3929,10 @@ var Properties = {
"marquee-style" : 1,
"max-height" : "<length> | <percentage> | <content-sizing> | none | inherit",
"max-width" : "<length> | <percentage> | <content-sizing> | none | inherit",
"max-zoom" : "<number> | <percentage> | auto",
"min-height" : "<length> | <percentage> | <content-sizing> | contain-floats | -moz-contain-floats | -webkit-contain-floats | inherit",
"min-width" : "<length> | <percentage> | <content-sizing> | contain-floats | -moz-contain-floats | -webkit-contain-floats | inherit",
"min-zoom" : "<number> | <percentage> | auto",
"move-to" : 1,
//N
@ -4045,6 +4047,7 @@ var Properties = {
"unicode-bidi" : "normal | embed | isolate | bidi-override | isolate-override | plaintext | inherit",
"user-modify" : "read-only | read-write | write-only | inherit",
"user-select" : "none | text | toggle | element | elements | all | inherit",
"user-zoom" : "zoom | fixed",
//V
"vertical-align" : "auto | use-script | baseline | sub | super | top | text-top | central | middle | bottom | text-bottom | <percentage> | <length>",

View File

@ -37,9 +37,9 @@ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
/* Exports are for Stylus and Less highlighters */
var supportType = exports.supportType = "align-content|align-items|align-self|all|animation|animation-delay|animation-direction|animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|backface-visibility|background|background-attachment|background-blend-mode|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|border|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|bottom|box-shadow|box-sizing|caption-side|clear|clip|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|cursor|direction|display|empty-cells|filter|flex|flex-basis|flex-direction|flex-flow|flex-grow|flex-shrink|flex-wrap|float|font|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|hanging-punctuation|height|justify-content|left|letter-spacing|line-height|list-style|list-style-image|list-style-position|list-style-type|margin|margin-bottom|margin-left|margin-right|margin-top|max-height|max-width|min-height|min-width|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|order|outline|outline-color|outline-offset|outline-style|outline-width|overflow|overflow-x|overflow-y|padding|padding-bottom|padding-left|padding-right|padding-top|page-break-after|page-break-before|page-break-inside|perspective|perspective-origin|position|quotes|resize|right|tab-size|table-layout|text-align|text-align-last|text-decoration|text-decoration-color|text-decoration-line|text-decoration-style|text-indent|text-justify|text-overflow|text-shadow|text-transform|top|transform|transform-origin|transform-style|transition|transition-delay|transition-duration|transition-property|transition-timing-function|unicode-bidi|vertical-align|visibility|white-space|width|word-break|word-spacing|word-wrap|z-index";
var supportType = exports.supportType = "align-content|align-items|align-self|all|animation|animation-delay|animation-direction|animation-duration|animation-fill-mode|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|backface-visibility|background|background-attachment|background-blend-mode|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|border|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|bottom|box-shadow|box-sizing|caption-side|clear|clip|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|cursor|direction|display|empty-cells|filter|flex|flex-basis|flex-direction|flex-flow|flex-grow|flex-shrink|flex-wrap|float|font|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|hanging-punctuation|height|justify-content|left|letter-spacing|line-height|list-style|list-style-image|list-style-position|list-style-type|margin|margin-bottom|margin-left|margin-right|margin-top|max-height|max-width|max-zoom|min-height|min-width|min-zoom|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|order|outline|outline-color|outline-offset|outline-style|outline-width|overflow|overflow-x|overflow-y|padding|padding-bottom|padding-left|padding-right|padding-top|page-break-after|page-break-before|page-break-inside|perspective|perspective-origin|position|quotes|resize|right|tab-size|table-layout|text-align|text-align-last|text-decoration|text-decoration-color|text-decoration-line|text-decoration-style|text-indent|text-justify|text-overflow|text-shadow|text-transform|top|transform|transform-origin|transform-style|transition|transition-delay|transition-duration|transition-property|transition-timing-function|unicode-bidi|user-select|user-zoom|vertical-align|visibility|white-space|width|word-break|word-spacing|word-wrap|z-index";
var supportFunction = exports.supportFunction = "rgb|rgba|url|attr|counter|counters";
var supportConstant = exports.supportConstant = "absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero";
var supportConstant = exports.supportConstant = "absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero|zoom";
var supportConstantColor = exports.supportConstantColor = "aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|rebeccapurple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen";
var supportConstantFonts = exports.supportConstantFonts = "arial|century|comic|courier|cursive|fantasy|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace";
@ -72,7 +72,7 @@ var CssHighlightRules = function() {
regex: "\\}"
}, {
token: "string",
regex: "@",
regex: "@(?!viewport)",
next: "media"
}, {
token: "keyword",
@ -140,7 +140,7 @@ var CssHighlightRules = function() {
include : ["strings", "url", "comments"]
}, {
token : ["constant.numeric", "keyword"],
regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)"
regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vmax|vmin|vm|vw|%)"
}, {
token : "constant.numeric",
regex : numRe

View File

@ -118,120 +118,120 @@ var eventAttributes = [
var globalAttributes = commonAttributes.concat(eventAttributes);
var attributeMap = {
"html": {"manifest": 1},
"head": {},
"title": {},
"base": {"href": 1, "target": 1},
"link": {"href": 1, "hreflang": 1, "rel": {"stylesheet": 1, "icon": 1}, "media": {"all": 1, "screen": 1, "print": 1}, "type": {"text/css": 1, "image/png": 1, "image/jpeg": 1, "image/gif": 1}, "sizes": 1},
"meta": {"http-equiv": {"content-type": 1}, "name": {"description": 1, "keywords": 1}, "content": {"text/html; charset=UTF-8": 1}, "charset": 1},
"style": {"type": 1, "media": {"all": 1, "screen": 1, "print": 1}, "scoped": 1},
"script": {"charset": 1, "type": {"text/javascript": 1}, "src": 1, "defer": 1, "async": 1},
"noscript": {"href": 1},
"body": {"onafterprint": 1, "onbeforeprint": 1, "onbeforeunload": 1, "onhashchange": 1, "onmessage": 1, "onoffline": 1, "onpopstate": 1, "onredo": 1, "onresize": 1, "onstorage": 1, "onundo": 1, "onunload": 1},
"section": {},
"nav": {},
"a": {"href": 1, "target": {"_blank": 1, "top": 1}, "ping": 1, "rel": {"nofollow": 1, "alternate": 1, "author": 1, "bookmark": 1, "help": 1, "license": 1, "next": 1, "noreferrer": 1, "prefetch": 1, "prev": 1, "search": 1, "tag": 1}, "media": 1, "hreflang": 1, "type": 1},
"abbr": {},
"address": {},
"area": {"shape": 1, "coords": 1, "href": 1, "hreflang": 1, "alt": 1, "target": 1, "media": 1, "rel": 1, "ping": 1, "type": 1},
"article": {"pubdate": 1},
"aside": {},
"audio": {"src": 1, "autobuffer": 1, "autoplay": {"autoplay": 1}, "loop": {"loop": 1}, "controls": {"controls": 1}, "muted": {"muted": 1}, "preload": {"auto": 1, "metadata": 1, "none": 1 }},
"b": {},
"base": {"href": 1, "target": 1},
"bdi": {},
"bdo": {},
"blockquote": {"cite": 1},
"body": {"onafterprint": 1, "onbeforeprint": 1, "onbeforeunload": 1, "onhashchange": 1, "onmessage": 1, "onoffline": 1, "onpopstate": 1, "onredo": 1, "onresize": 1, "onstorage": 1, "onundo": 1, "onunload": 1},
"br": {},
"button": {"autofocus": 1, "disabled": {"disabled": 1}, "form": 1, "formaction": 1, "formenctype": 1, "formmethod": 1, "formnovalidate": 1, "formtarget": 1, "name": 1, "value": 1, "type": {"button": 1, "submit": 1}},
"canvas": {"width": 1, "height": 1},
"caption": {},
"cite": {},
"code": {},
"col": {"span": 1},
"colgroup": {"span": 1},
"command": {"type": 1, "label": 1, "icon": 1, "disabled": 1, "checked": 1, "radiogroup": 1, "command": 1},
"data": {},
"datalist": {},
"dd": {},
"del": {"cite": 1, "datetime": 1},
"details": {"open": 1},
"dfn": {},
"dialog": {"open": 1},
"div": {},
"dl": {},
"dt": {},
"em": {},
"embed": {"src": 1, "height": 1, "width": 1, "type": 1},
"fieldset": {"disabled": 1, "form": 1, "name": 1},
"figcaption": {},
"figure": {},
"footer": {},
"form": {"accept-charset": 1, "action": 1, "autocomplete": 1, "enctype": {"multipart/form-data": 1, "application/x-www-form-urlencoded": 1}, "method": {"get": 1, "post": 1}, "name": 1, "novalidate": 1, "target": {"_blank": 1, "top": 1}},
"h1": {},
"h2": {},
"h3": {},
"h4": {},
"h5": {},
"h6": {},
"head": {},
"header": {},
"footer": {},
"address": {},
"main": {},
"p": {},
"hr": {},
"pre": {},
"blockquote": {"cite": 1},
"ol": {"start": 1, "reversed": 1},
"ul": {},
"li": {"value": 1},
"dl": {},
"dt": {},
"dd": {},
"figure": {},
"figcaption": {},
"div": {},
"a": {"href": 1, "target": {"_blank": 1, "top": 1}, "ping": 1, "rel": {"nofollow": 1, "alternate": 1, "author": 1, "bookmark": 1, "help": 1, "license": 1, "next": 1, "noreferrer": 1, "prefetch": 1, "prev": 1, "search": 1, "tag": 1}, "media": 1, "hreflang": 1, "type": 1},
"em": {},
"strong": {},
"small": {},
"s": {},
"cite": {},
"q": {"cite": 1},
"dfn": {},
"abbr": {},
"data": {},
"time": {"datetime": 1},
"code": {},
"var": {},
"samp": {},
"kbd": {},
"sub": {},
"sup": {},
"html": {"manifest": 1},
"i": {},
"b": {},
"u": {},
"mark": {},
"ruby": {},
"rt": {},
"rp": {},
"bdi": {},
"bdo": {},
"span": {},
"br": {},
"wbr": {},
"ins": {"cite": 1, "datetime": 1},
"del": {"cite": 1, "datetime": 1},
"img": {"alt": 1, "src": 1, "height": 1, "width": 1, "usemap": 1, "ismap": 1},
"iframe": {"name": 1, "src": 1, "height": 1, "width": 1, "sandbox": {"allow-same-origin": 1, "allow-top-navigation": 1, "allow-forms": 1, "allow-scripts": 1}, "seamless": {"seamless": 1}},
"embed": {"src": 1, "height": 1, "width": 1, "type": 1},
"object": {"param": 1, "data": 1, "type": 1, "height" : 1, "width": 1, "usemap": 1, "name": 1, "form": 1, "classid": 1},
"param": {"name": 1, "value": 1},
"video": {"src": 1, "autobuffer": 1, "autoplay": {"autoplay": 1}, "loop": {"loop": 1}, "controls": {"controls": 1}, "width": 1, "height": 1, "poster": 1, "muted": {"muted": 1}, "preload": {"auto": 1, "metadata": 1, "none": 1}},
"audio": {"src": 1, "autobuffer": 1, "autoplay": {"autoplay": 1}, "loop": {"loop": 1}, "controls": {"controls": 1}, "muted": {"muted": 1}, "preload": {"auto": 1, "metadata": 1, "none": 1 }},
"source": {"src": 1, "type": 1, "media": 1},
"track": {"kind": 1, "src": 1, "srclang": 1, "label": 1, "default": 1},
"canvas": {"width": 1, "height": 1},
"map": {"name": 1},
"area": {"shape": 1, "coords": 1, "href": 1, "hreflang": 1, "alt": 1, "target": 1, "media": 1, "rel": 1, "ping": 1, "type": 1},
"svg": {},
"math": {},
"table": {"summary": 1},
"caption": {},
"colgroup": {"span": 1},
"col": {"span": 1},
"tbody": {},
"thead": {},
"tfoot": {},
"tr": {},
"td": {"headers": 1, "rowspan": 1, "colspan": 1},
"th": {"headers": 1, "rowspan": 1, "colspan": 1, "scope": 1},
"form": {"accept-charset": 1, "action": 1, "autocomplete": 1, "enctype": {"multipart/form-data": 1, "application/x-www-form-urlencoded": 1}, "method": {"get": 1, "post": 1}, "name": 1, "novalidate": 1, "target": {"_blank": 1, "top": 1}},
"fieldset": {"disabled": 1, "form": 1, "name": 1},
"legend": {},
"label": {"form": 1, "for": 1},
"img": {"alt": 1, "src": 1, "height": 1, "width": 1, "usemap": 1, "ismap": 1},
"input": {
"type": {"text": 1, "password": 1, "hidden": 1, "checkbox": 1, "submit": 1, "radio": 1, "file": 1, "button": 1, "reset": 1, "image": 31, "color": 1, "date": 1, "datetime": 1, "datetime-local": 1, "email": 1, "month": 1, "number": 1, "range": 1, "search": 1, "tel": 1, "time": 1, "url": 1, "week": 1},
"accept": 1, "alt": 1, "autocomplete": {"on": 1, "off": 1}, "autofocus": {"autofocus": 1}, "checked": {"checked": 1}, "disabled": {"disabled": 1}, "form": 1, "formaction": 1, "formenctype": {"application/x-www-form-urlencoded": 1, "multipart/form-data": 1, "text/plain": 1}, "formmethod": {"get": 1, "post": 1}, "formnovalidate": {"formnovalidate": 1}, "formtarget": {"_blank": 1, "_self": 1, "_parent": 1, "_top": 1}, "height": 1, "list": 1, "max": 1, "maxlength": 1, "min": 1, "multiple": {"multiple": 1}, "name": 1, "pattern": 1, "placeholder": 1, "readonly": {"readonly": 1}, "required": {"required": 1}, "size": 1, "src": 1, "step": 1, "width": 1, "files": 1, "value": 1},
"button": {"autofocus": 1, "disabled": {"disabled": 1}, "form": 1, "formaction": 1, "formenctype": 1, "formmethod": 1, "formnovalidate": 1, "formtarget": 1, "name": 1, "value": 1, "type": {"button": 1, "submit": 1}},
"select": {"autofocus": 1, "disabled": 1, "form": 1, "multiple": {"multiple": 1}, "name": 1, "size": 1, "readonly":{"readonly": 1}},
"datalist": {},
"ins": {"cite": 1, "datetime": 1},
"kbd": {},
"keygen": {"autofocus": 1, "challenge": {"challenge": 1}, "disabled": {"disabled": 1}, "form": 1, "keytype": {"rsa": 1, "dsa": 1, "ec": 1}, "name": 1},
"label": {"form": 1, "for": 1},
"legend": {},
"li": {"value": 1},
"link": {"href": 1, "hreflang": 1, "rel": {"stylesheet": 1, "icon": 1}, "media": {"all": 1, "screen": 1, "print": 1}, "type": {"text/css": 1, "image/png": 1, "image/jpeg": 1, "image/gif": 1}, "sizes": 1},
"main": {},
"map": {"name": 1},
"mark": {},
"math": {},
"menu": {"type": 1, "label": 1},
"meta": {"http-equiv": {"content-type": 1}, "name": {"description": 1, "keywords": 1}, "content": {"text/html; charset=UTF-8": 1}, "charset": 1},
"meter": {"value": 1, "min": 1, "max": 1, "low": 1, "high": 1, "optimum": 1},
"nav": {},
"noscript": {"href": 1},
"object": {"param": 1, "data": 1, "type": 1, "height" : 1, "width": 1, "usemap": 1, "name": 1, "form": 1, "classid": 1},
"ol": {"start": 1, "reversed": 1},
"optgroup": {"disabled": 1, "label": 1},
"option": {"disabled": 1, "selected": 1, "label": 1, "value": 1},
"textarea": {"autofocus": {"autofocus": 1}, "disabled": {"disabled": 1}, "form": 1, "maxlength": 1, "name": 1, "placeholder": 1, "readonly": {"readonly": 1}, "required": {"required": 1}, "rows": 1, "cols": 1, "wrap": {"on": 1, "off": 1, "hard": 1, "soft": 1}},
"keygen": {"autofocus": 1, "challenge": {"challenge": 1}, "disabled": {"disabled": 1}, "form": 1, "keytype": {"rsa": 1, "dsa": 1, "ec": 1}, "name": 1},
"output": {"for": 1, "form": 1, "name": 1},
"p": {},
"param": {"name": 1, "value": 1},
"pre": {},
"progress": {"value": 1, "max": 1},
"meter": {"value": 1, "min": 1, "max": 1, "low": 1, "high": 1, "optimum": 1},
"details": {"open": 1},
"q": {"cite": 1},
"rp": {},
"rt": {},
"ruby": {},
"s": {},
"samp": {},
"script": {"charset": 1, "type": {"text/javascript": 1}, "src": 1, "defer": 1, "async": 1},
"select": {"autofocus": 1, "disabled": 1, "form": 1, "multiple": {"multiple": 1}, "name": 1, "size": 1, "readonly":{"readonly": 1}},
"small": {},
"source": {"src": 1, "type": 1, "media": 1},
"span": {},
"strong": {},
"style": {"type": 1, "media": {"all": 1, "screen": 1, "print": 1}, "scoped": 1},
"sub": {},
"sup": {},
"svg": {},
"table": {"summary": 1},
"tbody": {},
"td": {"headers": 1, "rowspan": 1, "colspan": 1},
"textarea": {"autofocus": {"autofocus": 1}, "disabled": {"disabled": 1}, "form": 1, "maxlength": 1, "name": 1, "placeholder": 1, "readonly": {"readonly": 1}, "required": {"required": 1}, "rows": 1, "cols": 1, "wrap": {"on": 1, "off": 1, "hard": 1, "soft": 1}},
"tfoot": {},
"th": {"headers": 1, "rowspan": 1, "colspan": 1, "scope": 1},
"thead": {},
"time": {"datetime": 1},
"title": {},
"tr": {},
"track": {"kind": 1, "src": 1, "srclang": 1, "label": 1, "default": 1},
"section": {},
"summary": {},
"command": {"type": 1, "label": 1, "icon": 1, "disabled": 1, "checked": 1, "radiogroup": 1, "command": 1},
"menu": {"type": 1, "label": 1},
"dialog": {"open": 1}
"u": {},
"ul": {},
"var": {},
"video": {"src": 1, "autobuffer": 1, "autoplay": {"autoplay": 1}, "loop": {"loop": 1}, "controls": {"controls": 1}, "width": 1, "height": 1, "poster": 1, "muted": {"muted": 1}, "preload": {"auto": 1, "metadata": 1, "none": 1}},
"wbr": {}
};
var elements = Object.keys(attributeMap);

View File

@ -38,12 +38,13 @@ define(function(require, exports, module) {
var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var KotlinHighlightRules = require("./kotlin_highlight_rules").KotlinHighlightRules;
// TODO: pick appropriate fold mode
var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour;
var FoldMode = require("./folding/cstyle").FoldMode;
var Mode = function() {
this.HighlightRules = KotlinHighlightRules;
this.foldingRules = new FoldMode();
this.$behaviour = new CstyleBehaviour();
};
oop.inherits(Mode, TextMode);

View File

@ -36,7 +36,7 @@ var TextMode = require("./text").Mode;
var LessHighlightRules = require("./less_highlight_rules").LessHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var CssBehaviour = require("./behaviour/css").CssBehaviour;
// var CssCompletions = require("./css_completions").CssCompletions;
var CssCompletions = require("./css_completions").CssCompletions;
var CStyleFoldMode = require("./folding/cstyle").FoldMode;
@ -44,7 +44,7 @@ var Mode = function() {
this.HighlightRules = LessHighlightRules;
this.$outdent = new MatchingBraceOutdent();
this.$behaviour = new CssBehaviour();
// this.$completer = new CssCompletions();
this.$completer = new CssCompletions();
this.foldingRules = new CStyleFoldMode();
};
oop.inherits(Mode, TextMode);

View File

@ -10,6 +10,7 @@ define(function(require, exports, module){
this.$outdent = new that.MatchingBraceOutdent;
}
this.$id = "ace/mode/livescript";
this.$behaviour = new (require("./behaviour/cstyle").CstyleBehaviour)();
}
indenter = RegExp('(?:[({[=:]|[-~]>|\\b(?:e(?:lse|xport)|d(?:o|efault)|t(?:ry|hen)|finally|import(?:\\s*all)?|const|var|let|new|catch(?:\\s*' + identifier + ')?))\\s*$');
prototype.getNextLineIndent = function(state, line, tab){

View File

@ -564,7 +564,7 @@ define(function(require, exports, module) {
// \* / ^ % , { } ] ( ) ; # - +
case 42: case 47: case 94: case 37: case 44: case 123: case 125:
case 93: case 40: case 41: case 59: case 35: case 45: case 43:
case 93: case 40: case 41: case 59: case 35: case 45: case 43: case 38: case 124:
return scanPunctuator(input.charAt(index));
}
@ -1708,6 +1708,7 @@ define(function(require, exports, module) {
case 42: case 47: case 37: return 7; // * / %
case 43: case 45: return 6; // + -
case 60: case 62: return 3; // < >
case 38: case 124: return 7; // & |
}
} else if (2 === length) {
switch (charCode) {

View File

@ -70,7 +70,7 @@ var MarkdownHighlightRules = function() {
token : function(value) {
return "markup.heading." + value.length;
},
regex : /^#{1,6}(?=\s*[^ #]|\s+#.)/,
regex : /^#{1,6}(?=\s|$)/,
next : "header"
},
github_embed("(?:javascript|js)", "jscode-"),

View File

@ -41,11 +41,11 @@ var NSISHighlightRules = function() {
this.$rules = {
start: [{
token: "keyword.compiler.nsis",
regex: /^\s*!(?:include|addincludedir|addplugindir|appendfile|cd|delfile|echo|error|execute|packhdr|pragma|finalize|getdllversion|system|tempfile|warning|verbose|define|undef|insertmacro|macro|macroend|makensis|searchparse|searchreplace)\b/,
regex: /^\s*!(?:include|addincludedir|addplugindir|appendfile|cd|delfile|echo|error|execute|packhdr|pragma|finalize|getdllversion|gettlbversion|system|tempfile|warning|verbose|define|undef|insertmacro|macro|macroend|makensis|searchparse|searchreplace)\b/,
caseInsensitive: true
}, {
token: "keyword.command.nsis",
regex: /^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetLabelAddress|GetTempFileName|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|IntCmp|IntCmpU|IntFmt|IntOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\b/,
regex: /^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetLabelAddress|GetTempFileName|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|Int64Cmp|Int64CmpU|Int64Fmt|IntCmp|IntCmpU|IntFmt|IntOp|IntPtrCmp|IntPtrCmpU|IntPtrOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|PEDllCharacteristics|PESubsysVer|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\b/,
caseInsensitive: true
}, {
token: "keyword.control.nsis",
@ -71,7 +71,7 @@ var NSISHighlightRules = function() {
caseInsensitive: true
}, {
token: "constant.library.nsis",
regex: /\${(?:AtLeastServicePack|AtLeastWin7|AtLeastWin8|AtLeastWin10|AtLeastWin95|AtLeastWin98|AtLeastWin2000|AtLeastWin2003|AtLeastWin2008|AtLeastWin2008R2|AtLeastWinME|AtLeastWinNT4|AtLeastWinVista|AtLeastWinXP|AtMostServicePack|AtMostWin7|AtMostWin8|AtMostWin10|AtMostWin95|AtMostWin98|AtMostWin2000|AtMostWin2003|AtMostWin2008|AtMostWin2008R2|AtMostWinME|AtMostWinNT4|AtMostWinVista|AtMostWinXP|IsNT|IsServer|IsServicePack|IsWin7|IsWin8|IsWin10|IsWin95|IsWin98|IsWin2000|IsWin2003|IsWin2008|IsWin2008R2|IsWinME|IsWinNT4|IsWinVista|IsWinXP)}/
regex: /\${(?:AtLeastServicePack|AtLeastWin7|AtLeastWin8|AtLeastWin10|AtLeastWin95|AtLeastWin98|AtLeastWin2000|AtLeastWin2003|AtLeastWin2008|AtLeastWin2008R2|AtLeastWinME|AtLeastWinNT4|AtLeastWinVista|AtLeastWinXP|AtMostServicePack|AtMostWin7|AtMostWin8|AtMostWin10|AtMostWin95|AtMostWin98|AtMostWin2000|AtMostWin2003|AtMostWin2008|AtMostWin2008R2|AtMostWinME|AtMostWinNT4|AtMostWinVista|AtMostWinXP|IsDomainController|IsNT|IsServer|IsServicePack|IsWin7|IsWin8|IsWin10|IsWin95|IsWin98|IsWin2000|IsWin2003|IsWin2008|IsWin2008R2|IsWinME|IsWinNT4|IsWinVista|IsWinXP)}/
}, {
token: "constant.language.boolean.true.nsis",
regex: /\b(?:true|on)\b/

View File

@ -9330,10 +9330,20 @@ var PhpCompletions = function() {
if (!token)
return [];
if (token.type==='support.php_tag' && token.value==='<?')
return this.getTagCompletions(state, session, pos, prefix);
// php function
if (token.type==='identifier')
if (token.type==='identifier') {
if (token.index > 0) {
var prevToken = session.getTokenAt(pos.row, token.start);
if (prevToken.type==='support.php_tag') {
return this.getTagCompletions(state, session, pos, prefix);
}
}
return this.getFunctionCompletions(state, session, pos, prefix);
}
// php variable
if (is(token, "variable"))
@ -9346,6 +9356,20 @@ var PhpCompletions = function() {
return [];
};
this.getTagCompletions = function(state, session, pos, prefix) {
return [{
caption: 'php',
value: 'php',
meta: "php tag",
score: Number.MAX_VALUE
}, {
caption: '=',
value: '=',
meta: "php tag",
score: Number.MAX_VALUE
}];
};
this.getFunctionCompletions = function(state, session, pos, prefix) {
var functions = Object.keys(functionMap);

View File

@ -1001,7 +1001,7 @@ var PhpLangHighlightRules = function() {
next: "heredoc"
}, {
token : "keyword.operator",
regex : "::|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|!=|!==|<=|>=|=>|<<=|>>=|>>>=|<>|<|>|=|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
regex : "::|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|!=|!==|<=|>=|=>|<<=|>>=|>>>=|<>|<|>|\\.=|=|!|&&|\\|\\||\\?\\:|\\*=|/=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"
}, {
token : "paren.lparen",
regex : "[[({]"

View File

@ -113,11 +113,11 @@ var PraatHighlightRules = function() {
{
// Interpolated strings
token : "string.interpolated",
regex : /'((?:[a-z][a-zA-Z0-9_]*)(?:\$|#|:[0-9]+)?)'/
regex : /'((?:\.?[a-z][a-zA-Z0-9_.]*)(?:\$|#|:[0-9]+)?)'/
}, {
// stopwatch
token : ["text", "text", "keyword.operator", "text", "keyword"],
regex : /(^\s*)(?:([a-z][a-zA-Z0-9_]*\$?\s+)(=)(\s+))?(stopwatch)/
regex : /(^\s*)(?:(\.?[a-z][a-zA-Z0-9_.]*\$?\s+)(=)(\s+))?(stopwatch)/
}, {
// Directives which introduce unquoted strings
token : ["text", "keyword", "text", "string"],
@ -133,7 +133,11 @@ var PraatHighlightRules = function() {
}, {
// Commands
token : ["text", "text", "keyword.operator", "text", "keyword", "text", "keyword"],
regex : /(^\s*)(?:([a-z][a-zA-Z0-9_]*\$?\s+)(=)(\s+))?(?:((?:no)?warn|(?:unix_)?nocheck|noprogress)(\s+))?((?:[A-Z][^.:"]+)(?:$|(?:\.{3}|:)))/
regex : /(^\s*)(?:(\.?[a-z][a-zA-Z0-9_.]*\$?\s+)(=)(\s+))?(?:((?:no)?warn|(?:unix_)?nocheck|noprogress)(\s+))?((?:[A-Z][^.:"]+)(?:$|(?:\.{3}|:)))/
}, {
// Editor mode
token : ["text", "keyword", "text", "keyword"],
regex : /(^\s*)((?:no(?:warn|check))?)(\s*)(\b(?:editor(?::?)|endeditor)\b)/
}, {
// Demo commands
token : ["text", "keyword", "text", "keyword"],
@ -188,7 +192,7 @@ var PraatHighlightRules = function() {
}, {
// Procedure declarations
token : ["keyword", "text", "entity.name.function"],
regex : /(procedure)(\s+)(\S+)/
regex : /(procedure)(\s+)([^:\s]+)/
}, {
// New-style procedure calls
token : ["entity.name.function", "text"],

View File

@ -64,7 +64,7 @@ var PythonHighlightRules = function() {
var keywordMapper = this.createKeywordMapper({
"invalid.deprecated": "debugger",
"support.function": builtinFunctions,
//"invalid.illegal": futureReserved,
"variable.language": "self|cls",
"constant.language": builtinConstants,
"keyword": keywords
}, "identifier");

View File

@ -49,7 +49,7 @@ oop.inherits(Mode, TextMode);
(function() {
this.lineCommentStart = ";";
this.blockCommentStart = "comment {";
this.blockComment = { start: "comment {", end: "}" };
this.getNextLineIndent = function(state, line, tab) {
var indent = this.$getIndent(line);

View File

@ -63,7 +63,7 @@ var RedHighlightRules = function() {
{token : "string.tag", regex : /</, next : "tag"},
{token : "string", regex : /"/, next : "string"},
{token : "string.other", regex : "{", next : "string.other"},
{token : "comment", regex : "comment [[{]", next : "comment"},
{token : "comment", regex : "comment [{]", next : "comment"},
{token : "comment", regex : /;.+$/},
//{token : "invalid", regex: "\\.{2,}"},
{token : "paren.map-start", regex : "#\\("},

59
plugins/node_modules/ace/lib/ace/mode/redshift.js generated vendored Normal file
View File

@ -0,0 +1,59 @@
/* ***** 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) {
var oop = require("../lib/oop");
var TextMode = require("../mode/text").Mode;
var RedshiftHighlightRules = require("./redshift_highlight_rules").RedshiftHighlightRules;
var Range = require("../range").Range;
var Mode = function() {
this.HighlightRules = RedshiftHighlightRules;
};
oop.inherits(Mode, TextMode);
(function() {
this.lineCommentStart = "--";
this.blockComment = {start: "/*", end: "*/"};
this.getNextLineIndent = function(state, line, tab) {
if (state == "start" || state == "keyword.statementEnd") {
return "";
} else {
return this.$getIndent(line); // Keep whatever indent the previous line has
}
};
this.$id = "ace/mode/redshift";
}).call(Mode.prototype);
exports.Mode = Mode;
});

View File

@ -0,0 +1,230 @@
/* ***** 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) {
var oop = require("../lib/oop");
var lang = require("../lib/lang");
var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules;
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
// Syntax highlighting for json.
var JsonHighlightRules = require("./json_highlight_rules").JsonHighlightRules;
var RedshiftHighlightRules = function() {
// Keywords, functions, operators last updated for pg 9.3.
var keywords = (
"aes128|aes256|all|allowoverwrite|analyse|analyze|and|any|array|as|asc|authorization|backup|" +
"between|binary|blanksasnull|both|bytedict|bzip2|case|cast|check|collate|column|constraint|create|credentials|" +
"cross|current_date|current_time|current_timestamp|current_user|current_user_id|default|deferrable|deflate|defrag|delta|" +
"delta32k|desc|disable|distinct|do|else|emptyasnull|enable|encode|encrypt|encryption|end|except|explicit|false|for|foreign|" +
"freeze|from|full|globaldict256|globaldict64k|grant|group|gzip|having|identity|ignore|ilike|in|initially|inner|intersect|into|is|" +
"isnull|join|leading|left|like|limit|localtime|localtimestamp|lun|luns|lzo|lzop|minus|mostly13|mostly32|mostly8|natural|new|not|notnull|" +
"null|nulls|off|offline|offset|old|on|only|open|or|order|outer|overlaps|parallel|partition|percent|permissions|placing|primary|raw|readratio|" +
"recover|references|rejectlog|resort|restore|right|select|session_user|similar|some|sysdate|system|table|tag|tdes|text255|text32k|then|timestamp|" +
"to|top|trailing|true|truncatecolumns|union|unique|user|using|verbose|wallet|when|where|with|without"
);
var builtinFunctions = (
"current_schema|current_schemas|has_database_privilege|has_schema_privilege|has_table_privilege|age|current_time|current_timestamp|localtime|" +
"isfinite|now|ascii|get_bit|get_byte|octet_length|set_bit|set_byte|to_ascii|avg|count|listagg|max|min|stddev_samp|stddev_pop|sum|var_samp|var_pop|" +
"bit_and|bit_or|bool_and|bool_or|avg|count|cume_dist|dense_rank|first_value|last_value|lag|lead|listagg|max|median|min|nth_value|ntile|percent_rank|" +
"percentile_cont|percentile_disc|rank|ratio_to_report|row_number|case|coalesce|decode|greatest|least|nvl|nvl2|nullif|add_months|age|convert_timezone|" +
"current_date|timeofday|current_time|current_timestamp|date_cmp|date_cmp_timestamp|date_part_year|dateadd|datediff|date_part|date_trunc|extract|getdate|" +
"interval_cmp|isfinite|last_day|localtime|localtimestamp|months_between|next_day|now|sysdate|timestamp_cmp|timestamp_cmp_date|trunc|abs|acos|asin|atan|" +
"atan2|cbrt|ceiling|ceil|checksum|cos|cot|degrees|dexp|dlog1|dlog10|exp|floor|ln|log|mod|pi|power|radians|random|round|sin|sign|sqrt|tan|trunc|ascii|" +
"bpcharcmp|btrim|bttext_pattern_cmp|char_length|character_length|charindex|chr|concat|crc32|func_sha1|get_bit|get_byte|initcap|left|right|len|length|" +
"lower|lpad|rpad|ltrim|md5|octet_length|position|quote_ident|quote_literal|regexp_count|regexp_instr|regexp_replace|regexp_substr|repeat|replace|replicate|" +
"reverse|rtrim|set_bit|set_byte|split_part|strpos|strtol|substring|textlen|to_ascii|to_hex|translate|trim|upper|json_array_length|json_extract_array_element_text|" +
"json_extract_path_text|cast|convert|to_char|to_date|to_number|current_database|current_schema|current_schemas|current_user|current_user_id|has_database_privilege|" +
"has_schema_privilege|has_table_privilege|pg_backend_pid|pg_last_copy_count|pg_last_copy_id|pg_last_query_id|pg_last_unload_count|session_user|slice_num|user|version"
);
var keywordMapper = this.createKeywordMapper({
"support.function": builtinFunctions,
"keyword": keywords
}, "identifier", true);
var sqlRules = [{
token : "string", // single line string -- assume dollar strings if multi-line for now
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
}, {
token : "variable.language", // pg identifier
regex : '".*?"'
}, {
token : "constant.numeric", // float
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
}, {
token : keywordMapper,
regex : "[a-zA-Z_][a-zA-Z0-9_$]*\\b" // TODO - Unicode in identifiers
}, {
token : "keyword.operator",
regex : "!|!!|!~|!~\\*|!~~|!~~\\*|#|##|#<|#<=|#<>|#=|#>|#>=|%|\\&|\\&\\&|\\&<|\\&<\\||\\&>|\\*|\\+|" +
"\\-|/|<|<#>|<\\->|<<|<<=|<<\\||<=|<>|<\\?>|<@|<\\^|=|>|>=|>>|>>=|>\\^|\\?#|\\?\\-|\\?\\-\\||" +
"\\?\\||\\?\\|\\||@|@\\-@|@>|@@|@@@|\\^|\\||\\|\\&>|\\|/|\\|>>|\\|\\||\\|\\|/|~|~\\*|~<=~|~<~|" +
"~=|~>=~|~>~|~~|~~\\*"
}, {
token : "paren.lparen",
regex : "[\\(]"
}, {
token : "paren.rparen",
regex : "[\\)]"
}, {
token : "text",
regex : "\\s+"
}
];
this.$rules = {
"start" : [{
token : "comment",
regex : "--.*$"
},
DocCommentHighlightRules.getStartRule("doc-start"),
{
token : "comment", // multi-line comment
regex : "\\/\\*",
next : "comment"
},{
token : "keyword.statementBegin",
regex : "^[a-zA-Z]+", // Could enumerate starting keywords but this allows things to work when new statements are added.
next : "statement"
},{
token : "support.buildin", // psql directive
regex : "^\\\\[\\S]+.*$"
}
],
"statement" : [{
token : "comment",
regex : "--.*$"
}, {
token : "comment", // multi-line comment
regex : "\\/\\*",
next : "commentStatement"
}, {
token : "statementEnd",
regex : ";",
next : "start"
}, {
token : "string",
regex : "\\$json\\$",
next : "json-start"
}, {
token : "string",
regex : "\\$[\\w_0-9]*\\$$", // dollar quote at the end of a line
next : "dollarSql"
}, {
token : "string",
regex : "\\$[\\w_0-9]*\\$",
next : "dollarStatementString"
}
].concat(sqlRules),
"dollarSql" : [{
token : "comment",
regex : "--.*$"
}, {
token : "comment", // multi-line comment
regex : "\\/\\*",
next : "commentDollarSql"
}, {
token : "string", // end quoting with dollar at the start of a line
regex : "^\\$[\\w_0-9]*\\$",
next : "statement"
}, {
token : "string",
regex : "\\$[\\w_0-9]*\\$",
next : "dollarSqlString"
}
].concat(sqlRules),
"comment" : [{
token : "comment", // closing comment
regex : ".*?\\*\\/",
next : "start"
}, {
token : "comment", // comment spanning whole line
regex : ".+"
}
],
"commentStatement" : [{
token : "comment", // closing comment
regex : ".*?\\*\\/",
next : "statement"
}, {
token : "comment", // comment spanning whole line
regex : ".+"
}
],
"commentDollarSql" : [{
token : "comment", // closing comment
regex : ".*?\\*\\/",
next : "dollarSql"
}, {
token : "comment", // comment spanning whole line
regex : ".+"
}
],
"dollarStatementString" : [{
token : "string", // closing dollarstring
regex : ".*?\\$[\\w_0-9]*\\$",
next : "statement"
}, {
token : "string", // dollarstring spanning whole line
regex : ".+"
}
],
"dollarSqlString" : [{
token : "string", // closing dollarstring
regex : ".*?\\$[\\w_0-9]*\\$",
next : "dollarSql"
}, {
token : "string", // dollarstring spanning whole line
regex : ".+"
}
]
};
this.embedRules(DocCommentHighlightRules, "doc-", [ DocCommentHighlightRules.getEndRule("start") ]);
this.embedRules(JsonHighlightRules, "json-", [{token : "string", regex : "\\$json\\$", next : "statement"}]);
};
oop.inherits(RedshiftHighlightRules, TextHighlightRules);
exports.RedshiftHighlightRules = RedshiftHighlightRules;
});

View File

@ -46,6 +46,8 @@ oop.inherits(Mode, TextMode);
this.lineCommentStart = "//";
this.blockComment = {start: "/*", end: "*/"};
this.$quotes = { '"': '"' };
this.$id = "ace/mode/verilog";
}).call(Mode.prototype);

View File

@ -75,11 +75,16 @@ var keywords = "always|and|assign|automatic|begin|buf|bufif0|bufif1|case|casex|c
{ defaultToken : "comment" }
]
}, {
token : "string", // " string
regex : '".*?"'
token : "string.start",
regex : '"',
next : [
{ token : "constant.language.escape", regex : /\\(?:[ntvfa\\"]|[0-7]{1,3}|\x[a-fA-F\d]{1,2}|)/, consumeLineEnd : true },
{ token : "string.end", regex : '"|$', next: "start" },
{ defaultToken : "string" }
]
}, {
token : "string", // ' string
regex : "'.*?'"
token : "string",
regex : "'^[']'"
}, {
token : "constant.numeric", // float
regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"

View File

@ -17,13 +17,13 @@ function copy(src,dest){
^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
*/
function _extends(Class,Super){
var t = function(){};
var pt = Class.prototype;
if(Object.create){
var ppt = Object.create(Super.prototype)
var ppt = Object.create(Super.prototype);
pt.__proto__ = ppt;
}
if(!(pt instanceof Super)){
function t(){};
t.prototype = Super.prototype;
t = new t();
copy(pt,t);
@ -31,14 +31,14 @@ function _extends(Class,Super){
}
if(pt.constructor != Class){
if(typeof Class != 'function'){
console.error("unknow Class:"+Class)
console.error("unknown Class:"+Class);
}
pt.constructor = Class
pt.constructor = Class;
}
}
var htmlns = 'http://www.w3.org/1999/xhtml' ;
// Node Types
var NodeType = {}
var NodeType = {};
var ELEMENT_NODE = NodeType.ELEMENT_NODE = 1;
var ATTRIBUTE_NODE = NodeType.ATTRIBUTE_NODE = 2;
var TEXT_NODE = NodeType.TEXT_NODE = 3;
@ -53,7 +53,7 @@ var DOCUMENT_FRAGMENT_NODE = NodeType.DOCUMENT_FRAGMENT_NODE = 11;
var NOTATION_NODE = NodeType.NOTATION_NODE = 12;
// ExceptionCode
var ExceptionCode = {}
var ExceptionCode = {};
var ExceptionMessage = {};
var INDEX_SIZE_ERR = ExceptionCode.INDEX_SIZE_ERR = ((ExceptionMessage[1]="Index size error"),1);
var DOMSTRING_SIZE_ERR = ExceptionCode.DOMSTRING_SIZE_ERR = ((ExceptionMessage[2]="DOMString size error"),2);
@ -100,14 +100,14 @@ NodeList.prototype = {
* The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
* @standard level1
*/
length:0,
length:0,
/**
* Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
* @standard level1
* @param index unsigned long
* @param index unsigned long
* Index into the collection.
* @return Node
* The node at the indexth position in the NodeList, or null if that is not a valid index.
* The node at the indexth position in the NodeList, or null if that is not a valid index.
*/
item: function(index) {
return this[index] || null;
@ -115,7 +115,7 @@ NodeList.prototype = {
};
function LiveNodeList(node,refresh){
this._node = node;
this._refresh = refresh
this._refresh = refresh;
_updateLiveList(this);
}
function _updateLiveList(list){
@ -135,10 +135,10 @@ LiveNodeList.prototype.item = function(i){
_extends(LiveNodeList,NodeList);
/**
*
*
* Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes.
* NamedNodeMap objects in the DOM are live.
* used for attributes or DocumentType entities
* used for attributes or DocumentType entities
*/
function NamedNodeMap() {
};
@ -168,9 +168,9 @@ function _addNamedNode(el,list,newAttr,oldAttr){
function _removeNamedNode(el,list,attr){
var i = _findNodeIndex(list,attr);
if(i>=0){
var lastIndex = list.length-1
var lastIndex = list.length-1;
while(i<lastIndex){
list[i] = list[++i]
list[i] = list[++i];
}
list.length = lastIndex;
if(el){
@ -181,7 +181,7 @@ function _removeNamedNode(el,list,attr){
}
}
}else{
throw new DOMException(NOT_FOUND_ERR,new Error())
throw new DOMException(NOT_FOUND_ERR,new Error());
}
}
NamedNodeMap.prototype = {
@ -224,10 +224,10 @@ NamedNodeMap.prototype = {
var attr = this.getNamedItem(key);
_removeNamedNode(this._ownerElement,this,attr);
return attr;
},// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
//for level2
removeNamedItemNS:function(namespaceURI,localName){
var attr = this.getNamedItemNS(namespaceURI,localName);
@ -290,7 +290,7 @@ DOMImplementation.prototype = {
node.systemId = systemId;
// Introduced in DOM Level 2:
//readonly attribute DOMString internalSubset;
//TODO:..
// readonly attribute NamedNodeMap entities;
// readonly attribute NamedNodeMap notations;
@ -320,10 +320,10 @@ Node.prototype = {
prefix : null,
localName : null,
// Modified in DOM Level 2:
insertBefore:function(newChild, refChild){//raises
insertBefore:function(newChild, refChild){//raises
return _insertBefore(this,newChild,refChild);
},
replaceChild:function(newChild, oldChild){//raises
replaceChild:function(newChild, oldChild){//raises
this.insertBefore(newChild,oldChild);
if(oldChild){
this.removeChild(oldChild);
@ -407,7 +407,7 @@ function _xmlEncoder(c){
c == '>' && '&gt;' ||
c == '&' && '&amp;' ||
c == '"' && '&quot;' ||
'&#'+c.charCodeAt()+';'
'&#'+c.charCodeAt()+';';
}
@ -446,7 +446,7 @@ function _onRemoveAttribute(doc,el,newAttr,remove){
var ns = newAttr.namespaceURI ;
if(ns == 'http://www.w3.org/2000/xmlns/'){
//update namespace
delete el._nsMap[newAttr.prefix?newAttr.localName:'']
delete el._nsMap[newAttr.prefix?newAttr.localName:''];
}
}
function _onUpdateChild(doc,el,newChild){
@ -472,7 +472,7 @@ function _onUpdateChild(doc,el,newChild){
/**
* attributes;
* children;
*
*
* writeable properties:
* nodeValue,Attr:value,CharacterData:data
* prefix
@ -514,8 +514,8 @@ function _insertBefore(parentNode,newChild,nextChild){
newFirst.previousSibling = pre;
newLast.nextSibling = nextChild;
if(pre){
pre.nextSibling = newFirst;
}else{
@ -564,8 +564,8 @@ Document.prototype = {
doctype : null,
documentElement : null,
_inc : 1,
insertBefore : function(newChild, refChild){//raises
insertBefore : function(newChild, refChild){//raises
if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
var child = newChild.firstChild;
while(child){
@ -578,7 +578,7 @@ Document.prototype = {
if(this.documentElement == null && newChild.nodeType == 1){
this.documentElement = newChild;
}
return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
},
removeChild : function(oldChild){
@ -601,10 +601,10 @@ Document.prototype = {
return true;
}
}
})
});
return rtv;
},
//document factory method:
createElement : function(tagName){
var node = new Element();
@ -625,19 +625,19 @@ Document.prototype = {
createTextNode : function(data){
var node = new Text();
node.ownerDocument = this;
node.appendData(data)
node.appendData(data);
return node;
},
createComment : function(data){
var node = new Comment();
node.ownerDocument = this;
node.appendData(data)
node.appendData(data);
return node;
},
createCDATASection : function(data){
var node = new CDATASection();
node.ownerDocument = this;
node.appendData(data)
node.appendData(data);
return node;
},
createProcessingInstruction : function(target,data){
@ -722,13 +722,13 @@ Element.prototype = {
setAttribute : function(name, value){
var attr = this.ownerDocument.createAttribute(name);
attr.value = attr.nodeValue = "" + value;
this.setAttributeNode(attr)
this.setAttributeNode(attr);
},
removeAttribute : function(name){
var attr = this.getAttributeNode(name)
var attr = this.getAttributeNode(name);
attr && this.removeAttributeNode(attr);
},
//four real opeartion method
appendChild:function(newChild){
if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
@ -751,7 +751,7 @@ Element.prototype = {
var old = this.getAttributeNodeNS(namespaceURI, localName);
old && this.removeAttributeNode(old);
},
hasAttributeNS : function(namespaceURI, localName){
return this.getAttributeNodeNS(namespaceURI, localName)!=null;
},
@ -762,12 +762,12 @@ Element.prototype = {
setAttributeNS : function(namespaceURI, qualifiedName, value){
var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
attr.value = attr.nodeValue = "" + value;
this.setAttributeNode(attr)
this.setAttributeNode(attr);
},
getAttributeNodeNS : function(namespaceURI, localName){
return this.attributes.getNamedItemNS(namespaceURI, localName);
},
getElementsByTagName : function(tagName){
return new LiveNodeList(this,function(base){
var ls = [];
@ -816,13 +816,12 @@ CharacterData.prototype = {
},
insertData: function(offset,text) {
this.replaceData(offset,0,text);
},
appendChild:function(newChild){
//if(!(newChild instanceof CharacterData)){
throw new Error(ExceptionMessage[3])
throw new Error(ExceptionMessage[3]);
//}
return Node.prototype.appendChild.apply(this,arguments)
return Node.prototype.appendChild.apply(this,arguments);
},
deleteData: function(offset, count) {
this.replaceData(offset,count,"");
@ -873,27 +872,27 @@ _extends(CDATASection,CharacterData);
function DocumentType() {
};
}
DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
_extends(DocumentType,Node);
function Notation() {
};
}
Notation.prototype.nodeType = NOTATION_NODE;
_extends(Notation,Node);
function Entity() {
};
}
Entity.prototype.nodeType = ENTITY_NODE;
_extends(Entity,Node);
function EntityReference() {
};
}
EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
_extends(EntityReference,Node);
function DocumentFragment() {
};
}
DocumentFragment.prototype.nodeName = "#document-fragment";
DocumentFragment.prototype.nodeType = DOCUMENT_FRAGMENT_NODE;
_extends(DocumentFragment,Node);
@ -919,7 +918,7 @@ function serializeToString(node,buf){
var len = attrs.length;
var child = node.firstChild;
var nodeName = node.tagName;
var isHTML = htmlns === node.namespaceURI
var isHTML = htmlns === node.namespaceURI;
buf.push('<',nodeName);
for(var i=0;i<len;i++){
serializeToString(attrs.item(i),buf);
@ -1054,12 +1053,12 @@ function cloneNode(doc,node,deep){
case ELEMENT_NODE:
var attrs = node.attributes;
var attrs2 = node2.attributes = new NamedNodeMap();
var len = attrs.length
var len = attrs.length;
attrs2._ownerElement = node2;
for(var i=0;i<len;i++){
node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
}
break;;
break;
case ATTRIBUTE_NODE:
deep = true;
}
@ -1074,9 +1073,26 @@ function cloneNode(doc,node,deep){
}
function __set__(object,key,value){
object[key] = value
object[key] = value;
}
//do dynamic
function getTextContent(node){
switch(node.nodeType){
case 1:
case 11:
var buf = [];
node = node.firstChild;
while(node){
if(node.nodeType!==7 && node.nodeType !==8){
buf.push(getTextContent(node));
}
node = node.nextSibling;
}
return buf.join('');
default:
return node.nodeValue;
}
}
try{
if(Object.defineProperty){
Object.defineProperty(LiveNodeList.prototype,'length',{
@ -1107,29 +1123,12 @@ try{
this.nodeValue = data;
}
}
})
function getTextContent(node){
switch(node.nodeType){
case 1:
case 11:
var buf = [];
node = node.firstChild;
while(node){
if(node.nodeType!==7 && node.nodeType !==8){
buf.push(getTextContent(node));
}
node = node.nextSibling;
}
return buf.join('');
default:
return node.nodeValue;
}
}
});
__set__ = function(object,key,value){
//console.log(value)
object['$$'+key] = value
}
object['$$'+key] = value;
};
}
}catch(e){//ie8
}

View File

@ -90,7 +90,7 @@ function DefaultHandlers(mouseHandler) {
// selection
if (inSelection && !editor.isFocused()) {
editor.focus();
if (this.$focusTimout && !this.$clickSelection && !editor.inMultiSelectMode) {
if (this.$focusTimeout && !this.$clickSelection && !editor.inMultiSelectMode) {
this.setState("focusWait");
this.captureMouse(ev);
return;
@ -185,7 +185,7 @@ function DefaultHandlers(mouseHandler) {
var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
var time = Date.now();
if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout)
if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimeout)
this.startSelect(this.mousedownEvent.getDocumentPosition());
};

View File

@ -218,7 +218,7 @@ config.defineOptions(MouseHandler.prototype, "mouseHandler", {
scrollSpeed: {initialValue: 2},
dragDelay: {initialValue: 150},
dragEnabled: {initialValue: true},
focusTimout: {initialValue: 0},
focusTimeout: {initialValue: 0},
tooltipFollowsMouse: {initialValue: true}
});

View File

@ -67,18 +67,22 @@ var Selection = function(session) {
this.clearSelection();
this.cursor = this.lead = this.doc.createAnchor(0, 0);
this.anchor = this.doc.createAnchor(0, 0);
this.$silent = false;
var self = this;
this.cursor.on("change", function(e) {
self._emit("changeCursor");
if (!self.$isEmpty)
self.$cursorChanged = true;
if (!self.$silent)
self._emit("changeCursor");
if (!self.$isEmpty && !self.$silent)
self._emit("changeSelection");
if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column)
self.$desiredColumn = null;
});
this.anchor.on("change", function() {
if (!self.$isEmpty)
self.$anchorChanged = true;
if (!self.$isEmpty && !self.$silent)
self._emit("changeSelection");
});
};
@ -131,6 +135,7 @@ var Selection = function(session) {
* @returns {Object}
* @related Anchor.getPosition
**/
this.getAnchor =
this.getSelectionAnchor = function() {
if (this.$isEmpty)
return this.getSelectionLead();
@ -146,31 +151,6 @@ var Selection = function(session) {
return this.lead.getPosition();
};
/**
* Shifts the selection up (or down, if [[Selection.isBackwards `isBackwards()`]] is true) the given number of columns.
* @param {Number} columns The number of columns to shift by
**/
this.shiftSelection = function(columns) {
if (this.$isEmpty) {
this.moveCursorTo(this.lead.row, this.lead.column + columns);
return;
}
var anchor = this.getSelectionAnchor();
var lead = this.getSelectionLead();
var isBackwards = this.isBackwards();
if (!isBackwards || anchor.column !== 0)
this.setSelectionAnchor(anchor.row, anchor.column + columns);
if (isBackwards || lead.column !== 0) {
this.$moveSelection(function() {
this.moveCursorTo(lead.row, lead.column + columns);
});
}
};
/**
* Returns `true` if the selection is going backwards in the document.
* @returns {Boolean}
@ -211,8 +191,7 @@ var Selection = function(session) {
* Selects all the text in the document.
**/
this.selectAll = function() {
this.setSelectionAnchor(0, 0);
this.cursor.setPosition(Number.MAX_VALUE, Number.MAX_VALUE);
this.$setSelection(0, 0, Number.MAX_VALUE, Number.MAX_VALUE);
};
/**
@ -227,10 +206,21 @@ var Selection = function(session) {
this.setSelectionRange = function(range, reverse) {
var start = reverse ? range.end : range.start;
var end = reverse ? range.start : range.end;
this.$isEmpty = !Range.comparePoints(start, end);
this.anchor.setPosition(start.row, start.column);
this.cursor.setPosition(end.row, end.column);
this.$setSelection(start.row, start.column, end.row, end.column);
};
this.$setSelection = function(anchorRow, anchorColumn, cursorRow, cursorColumn) {
var wasEmpty = this.$isEmpty;
this.$silent = true;
this.$cursorChanged = this.$anchorChanged = false;
this.anchor.setPosition(anchorRow, anchorColumn);
this.cursor.setPosition(cursorRow, cursorColumn);
this.$isEmpty = !Range.comparePoints(this.anchor, this.cursor);
this.$silent = false;
if (this.$cursorChanged)
this._emit("changeCursor");
if (this.$cursorChanged || this.$anchorChanged)
this._emit("changeSelection");
};
this.$moveSelection = function(mover) {

View File

@ -45,6 +45,16 @@ module.exports = {
var text = new Array(rows).join(line + "\n") + line;
return new EditSession(text);
},
"test: selectAll" : function() {
var session = this.createSession(10, 10);
var selection = session.selection;
session.selection.selectAll();
assert.position(selection.getAnchor(), 0, 0);
assert.position(selection.getCursor(), 9, 10);
assert.position(selection.getRange().end, 9, 10);
assert.position(selection.getRange().start, 0, 0);
},
"test: move cursor to end of file should place the cursor on last row and column" : function() {
var session = this.createSession(200, 10);
@ -455,6 +465,7 @@ module.exports = {
},
"test fromJSON/toJSON": function() {
var copy = function(data) { return JSON.parse(JSON.stringify(data)); };
var session = new EditSession("function (a) {\n \n}");
var selection = session.getSelection();
@ -462,15 +473,40 @@ module.exports = {
selection.moveCursorDown();
assert.position(selection.getCursor(), 1, 4);
var data = selection.toJSON();
data = JSON.parse(JSON.stringify(data));
selection.moveCursorDown();
assert.position(selection.getCursor(), 2, 1);
assert.ok(!selection.isEqual(data));
selection.fromJSON(data);
var nCursor = 0;
var nSelection = 0;
selection.on("changeCursor", function() { nCursor++; });
selection.on("changeSelection", function() { nSelection++; });
selection.fromJSON(copy(data));
assert.equal(nCursor, 1);
assert.equal(nSelection, 1);
assert.position(selection.getCursor(), 1, 4);
assert.ok(selection.isEqual(data));
data.end.column = 10;
selection.fromJSON(copy(data));
assert.equal(nCursor, 1);
assert.equal(nSelection, 1);
data.end.column = 4;
assert.ok(selection.isEqual(data));
data.start.row = 0;
selection.fromJSON(copy(data));
assert.equal(nCursor, 1);
assert.equal(nSelection, 2);
assert.ok(selection.isEqual(data));
data.isBackwards = true;
selection.fromJSON(copy(data));
assert.equal(nCursor, 2);
assert.equal(nSelection, 3);
assert.ok(selection.isEqual(data));
},
"test setRange inside fold": function() {
@ -481,6 +517,24 @@ module.exports = {
selection.setRange(new Range(1, 1, 1, 5));
assert.equal(session.getTextRange(), "fold");
},
"test selectLine": function() {
var session = new EditSession(" text -\n-fold- \n-");
var selection = session.getSelection();
selection.selectLine();
assert.range(selection.getRange(), 0, 0, 1, 0);
selection.clearSelection();
assert.position(selection.getAnchor(), 1, 0);
selection.moveCursorLineEnd();
assert.position(selection.getAnchor(), 1, 9);
selection.moveCursorLineEnd();
assert.position(selection.getAnchor(), 1, 6);
selection.selectLineStart();
assert.range(selection.getRange(), 1, 0, 1, 6);
}
};

View File

@ -92,6 +92,7 @@ if (location.search)
testNames = location.search.substr(1).split(",");
var filter = location.hash.substr(1);
window.onhashchange = function() { location.reload(); };
require(testNames, function() {
var tests = testNames.map(function(x) {

View File

@ -8,14 +8,14 @@
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
ace-dracula .ace_gutter {
.ace-dracula .ace_gutter {
background: #282a36;
color: rgb(144,145,148)
}
.ace-dracula .ace_print-margin {
width: 1px;
background: #e8e8e8
background: #44475a
}
.ace-dracula {
@ -42,7 +42,7 @@ ace-dracula .ace_gutter {
.ace-dracula .ace_marker-layer .ace_bracket {
margin: -1px 0 0 -1px;
border: 1px solid #3B3A32
border: 1px solid #a29709
}
.ace-dracula .ace_marker-layer .ace_active-line {
@ -54,7 +54,8 @@ ace-dracula .ace_gutter {
}
.ace-dracula .ace_marker-layer .ace_selected-word {
border: 1px solid #44475a
box-shadow: 0px 0px 0px 1px #a29709;
border-radius: 3px;
}
.ace-dracula .ace_fold {
@ -151,3 +152,10 @@ ace-dracula .ace_gutter {
.ace-dracula .ace_entity.ace_name.ace_tag {
color: #ff79c6
}
.ace-dracula .ace_invisible {
color: #626680;
}
.ace-dracula .ace_indent-guide {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHB3d/8PAAOIAdULw8qMAAAAAElFTkSuQmCC) right repeat-y
}

View File

@ -33,6 +33,7 @@ define(function(require, exports, module) {
exports.isDark = true;
exports.cssClass = "ace-dracula";
exports.cssText = require("../requirejs/text!./dracula.css");
exports.$selectionColorConflict = true;
var dom = require("../lib/dom");
dom.importCssString(exports.cssText, exports.cssClass);

View File

@ -34,6 +34,7 @@ define(function(require, exports, module) {
exports.isDark = false;
exports.cssClass = "ace-tm";
exports.cssText = require("../requirejs/text!./textmate.css");
exports.$id = "ace/theme/textmate";
var dom = require("../lib/dom");
dom.importCssString(exports.cssText, exports.cssClass);

View File

@ -69,7 +69,7 @@ function Tooltip (parentNode) {
* @param {String} text
**/
this.setText = function(text) {
dom.setInnerText(this.getElement(), text);
this.getElement().textContent = text;
};
/**

View File

@ -558,7 +558,7 @@ function moveDeltasByOne(redoStack, d) {
d = cloneDelta(d);
for (var j = redoStack.length; j--;) {
var deltaSet = redoStack[j];
for (var i = deltaSet.length; i--> 0;) {
for (var i = deltaSet.length; i-- > 0;) {
var x = deltaSet[i];
var xformed = xform(x, d);
d = xformed[0];

View File

@ -67,13 +67,6 @@ var VirtualRenderer = function(container, theme) {
this.container = container || dom.createElement("div");
// TODO: this breaks rendering in Cloud9 with multiple ace instances
// // Imports CSS once per DOM document ('ace_editor' serves as an identifier).
// dom.importCssString(editorCss, "ace_editor", container.ownerDocument);
// in IE <= 9 the native cursor always shines through
this.$keepTextAreaAtCursor = !useragent.isOldIE;
dom.addCssClass(this.container, "ace_editor");
this.setTheme(theme);
@ -628,16 +621,18 @@ var VirtualRenderer = function(container, theme) {
};
// move text input over the cursor
// this is required for iOS and IME
// this is required for IME
this.$moveTextAreaToCursor = function() {
if (!this.$keepTextAreaAtCursor)
var style = this.textarea.style;
if (!this.$keepTextAreaAtCursor) {
style.left = -100 + "px";
return;
}
var config = this.layerConfig;
var posTop = this.$cursorLayer.$pixelPos.top;
var posLeft = this.$cursorLayer.$pixelPos.left;
posTop -= config.offset;
var style = this.textarea.style;
var h = this.lineHeight;
if (posTop < 0 || posTop > config.height - h) {
style.top = style.left = "0";
@ -1414,21 +1409,38 @@ var VirtualRenderer = function(container, theme) {
};
this.pixelToScreenCoordinates = function(x, y) {
var canvasPos = this.scroller.getBoundingClientRect();
var canvasPos;
if (this.$hasCssTransforms) {
canvasPos = {top:0, left: 0};
var p = this.$fontMetrics.transformCoordinates([x, y]);
x = p[1] - this.gutterWidth;
y = p[0];
} else {
canvasPos = this.scroller.getBoundingClientRect();
}
var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding;
var offset = offsetX / this.characterWidth;
var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight);
var col = Math.round(offset);
var col = this.$blockCursor ? Math.floor(offset) : Math.round(offset);
return {row: row, column: col, side: offset - col > 0 ? 1 : -1, offsetX: offsetX};
};
this.screenToTextCoordinates = function(x, y) {
var canvasPos = this.scroller.getBoundingClientRect();
var canvasPos;
if (this.$hasCssTransforms) {
canvasPos = {top:0, left: 0};
var p = this.$fontMetrics.transformCoordinates([x, y]);
x = p[1] - this.gutterWidth;
y = p[0];
} else {
canvasPos = this.scroller.getBoundingClientRect();
}
var offsetX = x + this.scrollLeft - canvasPos.left - this.$padding;
var col = Math.round(offsetX / this.characterWidth);
var offset = offsetX / this.characterWidth;
var col = this.$blockCursor ? Math.floor(offset) : Math.round(offset);
var row = (y + this.scrollTop - canvasPos.top) / this.lineHeight;
@ -1538,10 +1550,12 @@ var VirtualRenderer = function(container, theme) {
return cb && cb();
if (!module || !module.cssClass)
throw new Error("couldn't load module " + theme + " or it didn't call define");
if (module.$id)
_self.$themeId = module.$id;
dom.importCssString(
module.cssText,
module.cssClass,
_self.container.ownerDocument
_self.container
);
if (_self.theme)
@ -1612,6 +1626,10 @@ var VirtualRenderer = function(container, theme) {
this.setMouseCursor = function(cursorStyle) {
this.scroller.style.cursor = cursorStyle;
};
this.attachToShadowRoot = function() {
dom.importCssString(editorCss, "ace_editor.css", this.container);
};
/**
* Destroys the text and cursor layers for this renderer.
@ -1768,6 +1786,8 @@ config.defineOptions(VirtualRenderer.prototype, "renderer", {
get: function() { return this.$themeId || this.theme; },
initialValue: "./theme/textmate",
handlesSet: true
},
hasCssTransforms: {
}
});

View File

@ -36,10 +36,17 @@ if (typeof process !== "undefined") {
define(function(require, exports, module) {
"use strict";
var Editor = require("./edit_session").Editor;
var Editor = require("./editor").Editor;
var EditSession = require("./edit_session").EditSession;
var VirtualRenderer = require("./virtual_renderer").VirtualRenderer;
var assert = require("./test/assertions");
require("./ext/error_marker");
function setScreenPosition(node, rect) {
node.getBoundingClientRect = function() {
return { left: rect[0], top: rect[1], width: rect[2], height: rect[3] };
};
}
var editor = null;
module.exports = {
@ -64,7 +71,6 @@ module.exports = {
editor = null;
},
"test: screen2text the column should be rounded to the next character edge" : function(done) {
if (!editor) return done();
var renderer = editor.renderer;
renderer.setPadding(0);
@ -86,21 +92,76 @@ module.exports = {
testPixelToText(15, 0, 0, 2);
done();
},
"test: handle css transforms" : function(done) {
var renderer = editor.renderer;
var fontMetrics = renderer.$fontMetrics;
setScreenPosition(editor.container, [20, 30, 300, 100]);
var measureNode = fontMetrics.$measureNode;
setScreenPosition(measureNode, [0, 0, 10 * measureNode.textContent.length, 15]);
setScreenPosition(fontMetrics.$main, [0, 0, 10 * measureNode.textContent.length, 15]);
fontMetrics.$characterSize.width = 10;
renderer.setPadding(0);
renderer.onResize(true);
assert.equal(fontMetrics.getCharacterWidth(), 1);
renderer.characterWidth = 10;
renderer.lineHeight = 15;
renderer.gutterWidth = 40;
editor.setOption("hasCssTransforms", true);
editor.container.style.transform = "matrix3d(0.7, 0, 0, -0.00066, 0, 0.82, 0, -0.001, 0, 0, 1, 0, -100, -20, 10, 1)";
editor.container.style.zoom = 1.5;
var pos = renderer.pixelToScreenCoordinates(100, 200);
var els = fontMetrics.els;
var rects = [
[0, 0],
[-37.60084843635559, 161.62494659423828],
[114.50254130363464, -6.890693664550781],
[98.85665202140808, 179.16063690185547]
];
rects.forEach(function(rect, i) {
els[i].getBoundingClientRect = function() {
return { left: rect[0], top: rect[1] };
};
});
var r0 = els[0].getBoundingClientRect();
pos = renderer.pixelToScreenCoordinates(r0.left + 100, r0.top + 200);
assert.position(pos, 10, 11);
var pos1 = fontMetrics.transformCoordinates(null, [0, 200]);
assert.ok(pos1[0] - rects[2][0] < 10e-6);
assert.ok(pos1[1] - rects[2][1] < 10e-6);
done();
},
"test scrollmargin + autosize": function(done) {
if (!editor) return done();
editor.setOptions({
maxLines: 100,
useWrapMode: true
wrap: true
});
editor.renderer.setScrollMargin(10, 10);
editor.setValue("\n\n");
editor.setValue("\n\n\n\n");
if (editor.container.offsetWidth == undefined)
return done(); // jsdom
editor.renderer.once("afterRender", function() {
setTimeout(function() {
done();
}, 0);
});
},
"test line widgets": function() {
editor.session.setValue("a\nb|c\nd");
editor.session.setAnnotations([{row: 1, column: 2, type: "error"}]);
editor.execCommand(editor.commands.byName.goToNextError);
assert.position(editor.getCursorPosition(), 1, 2);
assert.ok(editor.session.lineWidgets[1]);
}
// change tab size after setDocument (for text layer)