diff --git a/plugins/node_modules/ace/lib/ace/ace.js b/plugins/node_modules/ace/lib/ace/ace.js index 93af50a1..6cc536c3 100644 --- a/plugins/node_modules/ace/lib/ace/ace.js +++ b/plugins/node_modules/ace/lib/ace/ace.js @@ -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"; }); diff --git a/plugins/node_modules/ace/lib/ace/autocomplete.js b/plugins/node_modules/ace/lib/ace/autocomplete.js index 8b362c23..3b99f03c 100644 --- a/plugins/node_modules/ace/lib/ace/autocomplete.js +++ b/plugins/node_modules/ace/lib/ace/autocomplete.js @@ -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; diff --git a/plugins/node_modules/ace/lib/ace/commands/default_commands.js b/plugins/node_modules/ace/lib/ace/commands/default_commands.js index f7c6d5f5..527bebe8 100644 --- a/plugins/node_modules/ace/lib/ace/commands/default_commands.js +++ b/plugins/node_modules/ace/lib/ace/commands/default_commands.js @@ -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); }); }, diff --git a/plugins/node_modules/ace/lib/ace/document.js b/plugins/node_modules/ace/lib/ace/document.js index 245f66ba..17f94427 100644 --- a/plugins/node_modules/ace/lib/ace/document.js +++ b/plugins/node_modules/ace/lib/ace/document.js @@ -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}; }; /** diff --git a/plugins/node_modules/ace/lib/ace/document_test.js b/plugins/node_modules/ace/lib/ace/document_test.js index 30048470..bcb6e877 100644 --- a/plugins/node_modules/ace/lib/ace/document_test.js +++ b/plugins/node_modules/ace/lib/ace/document_test.js @@ -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"); } }; diff --git a/plugins/node_modules/ace/lib/ace/edit_session.js b/plugins/node_modules/ace/lib/ace/edit_session.js index fdd75858..e09b7e9c 100644 --- a/plugins/node_modules/ace/lib/ace/edit_session.js +++ b/plugins/node_modules/ace/lib/ace/edit_session.js @@ -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 diff --git a/plugins/node_modules/ace/lib/ace/editor.js b/plugins/node_modules/ace/lib/ace/editor.js index 1ec567f0..9dfc7513 100644 --- a/plugins/node_modules/ace/lib/ace/editor.js +++ b/plugins/node_modules/ace/lib/ace/editor.js @@ -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", diff --git a/plugins/node_modules/ace/lib/ace/editor_commands_test.js b/plugins/node_modules/ace/lib/ace/editor_commands_test.js new file mode 100644 index 00000000..7819d999 --- /dev/null +++ b/plugins/node_modules/ace/lib/ace/editor_commands_test.js @@ -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(" abcd", 1); + exec("gotostart", 1); + exec("gotoright", 3); + editor.execCommand(editor.commands.byName.selecttomatching); + assert.range(editor.selection.getRange(), 0, 3, 0, 24); + + editor.setValue("
abcd
", 1); + exec("gotostart", 1); + exec("gotoright", 11); + editor.execCommand(editor.commands.byName.selecttomatching); + assert.range(editor.selection.getRange(), 0, 11, 0, 26); + + editor.setValue("
abcd
", 1); + exec("gotostart", 1); + exec("gotoright", 22); + editor.execCommand(editor.commands.byName.selecttomatching); + assert.range(editor.selection.getRange(), 0, 20, 0, 22); + + editor.setValue("abcd
", 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("abcd
", 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("abcd", 1); + exec("gotostart", 1); + exec("gotoright", 6); + editor.execCommand(editor.commands.byName.selecttomatching); + // TODO: assert.range should return selection until the instead of + + editor.setValue("abcd\n", 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(); +} \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/editor_highlight_selected_word_test.js b/plugins/node_modules/ace/lib/ace/editor_highlight_selected_word_test.js index 45a7d2e5..2c98492a 100644 --- a/plugins/node_modules/ace/lib/ace/editor_highlight_selected_word_test.js +++ b/plugins/node_modules/ace/lib/ace/editor_highlight_selected_word_test.js @@ -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"); diff --git a/plugins/node_modules/ace/lib/ace/ext/beautify.js b/plugins/node_modules/ace/lib/ace/ext/beautify.js index 89d94055..f6347b8f 100644 --- a/plugins/node_modules/ace/lib/ace/ext/beautify.js +++ b/plugins/node_modules/ace/lib/ace/ext/beautify.js @@ -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 +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 === " 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=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 === "" && 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" }]; -}); \ No newline at end of file +}); diff --git a/plugins/node_modules/ace/lib/ace/ext/beautify/php_rules.js b/plugins/node_modules/ace/lib/ace/ext/beautify/php_rules.js deleted file mode 100644 index ad851e9f..00000000 --- a/plugins/node_modules/ace/lib/ace/ext/beautify/php_rules.js +++ /dev/null @@ -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: '' -}, { - 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: '' ){ - 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 = false; - } - - //next token - lastTag = tag; - - lastToken = token; - - token = nextToken; - - if (token===null) { - break; - } - } - - return code; -}; - - - -}); diff --git a/plugins/node_modules/ace/lib/ace/ext/beautify_test.js b/plugins/node_modules/ace/lib/ace/ext/beautify_test.js new file mode 100644 index 00000000..aff7021c --- /dev/null +++ b/plugins/node_modules/ace/lib/ace/ext/beautify_test.js @@ -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([ + "
", + "

test

", + "
" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "
\n" + + "\t

test

\n" + + "
"); + + next(); + }, + + "test beautify block tag line breaks and indentation": function(next) { + var s = new EditSession([ + "
" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "\n" + + "\n" + + "\t
\n" + + "\n" + + ""); + + next(); + }, + + "test beautify empty block tag": function(next) { + var s = new EditSession([ + "\t
" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "
"); + + next(); + }, + + "test beautify inline tag indentation": function(next) { + var s = new EditSession([ + "
", + "hello world", + "
" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "
\n" + + "\thello world\n" + + "
"); + + next(); + }, + + "test beautify multiline inline tag indentation": function(next) { + var s = new EditSession([ + "
", + "", + "hello world", + "", + "
" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "
\n" + + "\t\n" + + "\t\thello world\n" + + "\t\n" + + "
"); + + next(); + }, + + "test beautify singleton tag indentation": function(next) { + var s = new EditSession([ + "
", + "hello
", + "world", + "
" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "
\n" + + "\thello
\n" + + "\tworld\n" + + "
"); + + next(); + }, + + "test beautify unknown singleton indentation": function(next) { + var s = new EditSession([ + "
", + "hello", + "world", + "
" + ], new PHPMode()); + s.setUseSoftTabs(false); + + beautify.beautify(s); + assert.equal(s.getValue(), "
\n" + + "\thello\n" + + "\tworld\n" + + "
"); + + next(); + }, + + "test beautify curly indentation": function(next) { + var s = new EditSession([ + ">} - */ -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: ' 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.} 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.} 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.} tokens Tokens to be merged. - * @return {Array.} 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.} 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 - } -}); - -}); diff --git a/plugins/node_modules/ace/lib/ace/ext/menu_tools/add_editor_menu_options.js b/plugins/node_modules/ace/lib/ace/ext/menu_tools/add_editor_menu_options.js deleted file mode 100644 index eb90e31d..00000000 --- a/plugins/node_modules/ace/lib/ace/ext/menu_tools/add_editor_menu_options.js +++ /dev/null @@ -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
- * 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - }; - }); -}; - - -}); diff --git a/plugins/node_modules/ace/lib/ace/ext/menu_tools/element_generator.js b/plugins/node_modules/ace/lib/ace/ext/menu_tools/element_generator.js deleted file mode 100644 index ec6ba93b..00000000 --- a/plugins/node_modules/ace/lib/ace/ext/menu_tools/element_generator.js +++ /dev/null @@ -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
- * Contains methods for generating elements. - * @author - * Matthew Christopher Kastor-Inare III
- * ☭ Hial Atropa!! ☭ - */ - -define(function(require, exports, module) { -'use strict'; -/** - * Creates a DOM option element - * @author - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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; -}; - -}); \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/ext/menu_tools/generate_settings_menu.js b/plugins/node_modules/ace/lib/ace/ext/menu_tools/generate_settings_menu.js deleted file mode 100644 index a15c26dd..00000000 --- a/plugins/node_modules/ace/lib/ace/ext/menu_tools/generate_settings_menu.js +++ /dev/null @@ -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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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(); -}; - -}); \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/ext/menu_tools/get_set_functions.js b/plugins/node_modules/ace/lib/ace/ext/menu_tools/get_set_functions.js deleted file mode 100644 index 4cd65508..00000000 --- a/plugins/node_modules/ace/lib/ace/ext/menu_tools/get_set_functions.js +++ /dev/null @@ -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
- * Gets various functions for setting settings. - * @author - * Matthew Christopher Kastor-Inare III
- * ☭ Hial Atropa!! ☭ - */ - -define(function(require, exports, module) { -'use strict'; -/** - * Generates a list of set functions for the settings menu. - * @author - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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 - * Matthew Christopher Kastor-Inare III
- * ☭ 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; -}; - -}); \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/ext/menu_tools/settings_menu.css b/plugins/node_modules/ace/lib/ace/ext/menu_tools/settings_menu.css index f8b761ce..8961e430 100644 --- a/plugins/node_modules/ace/lib/ace/ext/menu_tools/settings_menu.css +++ b/plugins/node_modules/ace/lib/ace/ext/menu_tools/settings_menu.css @@ -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; } \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/ext/modelist.js b/plugins/node_modules/ace/lib/ace/ext/modelist.js index 845c0917..942ce142 100644 --- a/plugins/node_modules/ace/lib/ace/ext/modelist.js +++ b/plugins/node_modules/ace/lib/ace/ext/modelist.js @@ -72,6 +72,7 @@ var supportedModes = { Dockerfile: ["^Dockerfile"], Dot: ["dot"], Drools: ["drl"], + Edifact: ["edi"], Eiffel: ["e|ge"], EJS: ["ejs"], Elixir: ["ex|exs"], diff --git a/plugins/node_modules/ace/lib/ace/ext/options.js b/plugins/node_modules/ace/lib/ace/ext/options.js new file mode 100644 index 00000000..9014aeb5 --- /dev/null +++ b/plugins/node_modules/ace/lib/ace/ext/options.js @@ -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; + +}); diff --git a/plugins/node_modules/ace/lib/ace/ext/settings_menu.js b/plugins/node_modules/ace/lib/ace/ext/settings_menu.js index 44f6d6ad..7ead5f9e 100644 --- a/plugins/node_modules/ace/lib/ace/ext/settings_menu.js +++ b/plugins/node_modules/ace/lib/ace/ext/settings_menu.js @@ -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(); + } } /** diff --git a/plugins/node_modules/ace/lib/ace/ext/textarea.js b/plugins/node_modules/ace/lib/ace/ext/textarea.js index 54806f99..cced80dc 100644 --- a/plugins/node_modules/ace/lib/ace/ext/textarea.js +++ b/plugins/node_modules/ace/lib/ace/ext/textarea.js @@ -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; diff --git a/plugins/node_modules/ace/lib/ace/ext/themelist.js b/plugins/node_modules/ace/lib/ace/ext/themelist.js index 10deca15..aa8b79d4 100644 --- a/plugins/node_modules/ace/lib/ace/ext/themelist.js +++ b/plugins/node_modules/ace/lib/ace/ext/themelist.js @@ -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"], diff --git a/plugins/node_modules/ace/lib/ace/keyboard/emacs.js b/plugins/node_modules/ace/lib/ace/keyboard/emacs.js index f048426e..fe8be728 100644 --- a/plugins/node_modules/ace/lib/ace/keyboard/emacs.js +++ b/plugins/node_modules/ace/lib/ace/keyboard/emacs.js @@ -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", diff --git a/plugins/node_modules/ace/lib/ace/keyboard/textinput.js b/plugins/node_modules/ace/lib/ace/keyboard/textinput.js index f9496a25..3703e4af 100644 --- a/plugins/node_modules/ace/lib/ace/keyboard/textinput.js +++ b/plugins/node_modules/ace/lib/ace/keyboard/textinput.js @@ -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) { diff --git a/plugins/node_modules/ace/lib/ace/keyboard/vim.js b/plugins/node_modules/ace/lib/ace/keyboard/vim.js index eebabc5a..d8676fac 100644 --- a/plugins/node_modules/ace/lib/ace/keyboard/vim.js +++ b/plugins/node_modules/ace/lib/ace/keyboard/vim.js @@ -26,7 +26,7 @@ * 2. Variable declarations and short basic helpers * 3. Instance (External API) implementation * 4. Internal state tracking objects (input state, counter) implementation - * and instanstiation + * and instantiation * 5. Key handler (the main command dispatcher) implementation * 6. Motion, operator, and action implementations * 7. Helper functions for the key handler, motions, operators, and actions @@ -97,11 +97,10 @@ define(function(require, exports, module) { newlineAndIndent: function(cm) { cm.ace.insert("\n"); } }; CodeMirror.keyMap = {}; - CodeMirror.addClass = CodeMirror.rmClass = - CodeMirror.e_stop = function() {}; + CodeMirror.addClass = CodeMirror.rmClass = function() {}; + CodeMirror.e_stop = CodeMirror.e_preventDefault = event.stopEvent; CodeMirror.keyName = function(e) { - if (e.key) return e.key; - var key = (KEYS[e.keyCode] || ""); + var key = (KEYS[e.keyCode] || e.key || ""); if (key.length == 1) key = key.toUpperCase(); key = event.getModifierString(e).replace(/(^|-)\w/g, function(m) { return m.toUpperCase(); @@ -554,7 +553,7 @@ define(function(require, exports, module) { highlight.session.on("changeEditor", highlight.destroy); highlight.session.on("change", highlight.updateOnChange); } - var re = new RegExp(o.query.source, "gm" + (o.query.ignoreCase ? "i" : "")); + var re = new RegExp(o.query.source, "gmi"); this.$searchHighlight = o.highlight = highlight; this.$searchHighlight.setRegexp(re); this.ace.renderer.updateBackMarkers(); @@ -603,7 +602,7 @@ define(function(require, exports, module) { return toCmPos(this.ace.session.doc.indexToPosition(index)); }; this.focus = function(index) { - return this.ace.focus(); + return this.ace.textInput.focus(); }; this.blur = function(index) { return this.ace.blur(); @@ -739,6 +738,23 @@ dom.importCssString(".normal-mode .ace_cursor{\ font-family: monospace;\ }", "vimMode"); (function() { + function dialogDiv(cm, template, bottom) { + var wrap = cm.ace.container; + var dialog; + dialog = wrap.appendChild(document.createElement("div")); + if (bottom) + dialog.className = "ace_dialog ace_dialog-bottom"; + else + dialog.className = "ace_dialog ace_dialog-top"; + + if (typeof template == "string") { + dialog.innerHTML = template; + } else { // Assuming it's a detached DOM element. + dialog.appendChild(template); + } + return dialog; + } + function closeNotification(cm, newVal) { if (cm.state.currentNotificationClose) cm.state.currentNotificationClose(); @@ -750,92 +766,82 @@ dom.importCssString(".normal-mode .ace_cursor{\ if (!options) options = {}; closeNotification(this, null); - - if (!options.onKeyDown && !options.onKeyUp) { - return this.openNotification(template, {}); - } + var dialog = dialogDiv(this, template, options.bottom); var closed = false, me = this; function close(newVal) { if (typeof newVal == 'string') { - ace.cmdLine.setValue(prefix + newVal, 1); + inp.value = newVal; } else { if (closed) return; closed = true; + dialog.parentNode.removeChild(dialog); me.focus(); - - CodeMirror.off(inp, "keyup", onKeyup); - ace.cmdLine.container.removeEventListener("keydown", onKeyDown, true); - CodeMirror.off(inp, "blur", onBlur); - - ace.cmdLine.setValue(""); + + if (options.onClose) options.onClose(dialog); } } - var ace = this.ace; - var cm = this; - var prefix = template; - if (prefix == ":") - return; - ace.showCommandLine(prefix, { - focus: true - }); - - if (options.value) { - var start = ace.cmdLine.getCursorPosition(); - var end = ace.cmdLine.session.insert(options.value); - ace.cmdLine.selection.setRange(Range.fromPoints(start, end)); - } - - function getVal() { - return ace.cmdLine.getValue().substring(prefix.length); - } - var inp = ace.cmdLine.textInput.getElement(); - var onKeyup = function(e) { - cm.operation(function() { - options.onKeyUp(e, getVal(), close); - if (!ace.cmdLine.getValue()) - close(); - }); - }; - var onKeyDown = function(e) { - cm.operation(function() { - var val = getVal(); - if (options && options.onKeyDown && options.onKeyDown(e, val, close)) { return; } + var inp = dialog.getElementsByTagName("input")[0], button; + if (inp) { + if (options.value) { + inp.value = options.value; + if (options.selectValueOnOpen !== false) inp.select(); + } + + if (options.onInput) + CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); + if (options.onKeyUp) + CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); + + CodeMirror.on(inp, "keydown", function(e) { + if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { + inp.blur(); CodeMirror.e_stop(e); close(); } - if (e.keyCode == 13) callback(val); + if (e.keyCode == 13) callback(inp.value); }); - }; - var onBlur = close; - if (options.onKeyUp) - CodeMirror.on(inp, "keyup", onKeyup); - ace.cmdLine.container.addEventListener("keydown", onKeyDown, true); - if (options.closeOnBlur !== false) - CodeMirror.on(inp, "blur", onBlur); - - + + if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); + + inp.focus(); + } else if (button = dialog.getElementsByTagName("button")[0]) { + CodeMirror.on(button, "click", function() { + close(); + me.focus(); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); + + button.focus(); + } return close; }); CodeMirror.defineExtension("openNotification", function(template, options) { if (this.virtualSelectionMode()) return; closeNotification(this, close); - var ace = this.ace; - ace.showCommandLine(undefined, { - timeout: options.duration, - message: template.replace(/<[^>]+>/g, ""), - focus: false - }); - var closed = false; + var dialog = dialogDiv(this, template, options && options.bottom); + var closed = false, doneTimer; + var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; function close() { - if (closed || !ace.cmdLine) return; + if (closed) return; closed = true; - ace.cmdLine.setMessage(""); + clearTimeout(doneTimer); + dialog.parentNode.removeChild(dialog); } + + CodeMirror.on(dialog, 'click', function(e) { + CodeMirror.e_preventDefault(e); + close(); + }); + + if (duration) + doneTimer = setTimeout(close, duration); + return close; }); })(); @@ -869,6 +875,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ { keys: '', type: 'keyToKey', toKeys: '' }, { keys: '', type: 'keyToKey', toKeys: '' }, { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, + { keys: '', type: 'action', action: 'toggleOverwrite', context: 'insert' }, // Motions { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, @@ -986,6 +993,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ { keys: '.', type: 'action', action: 'repeatLastEdit' }, { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, + { keys: '', type: 'action', action: 'indent', actionArgs: { indentRight: true }, context: 'insert' }, + { keys: '', type: 'action', action: 'indent', actionArgs: { indentRight: false }, context: 'insert' }, // Text object motions { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, @@ -1023,6 +1032,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ { name: 'sort', shortName: 'sor' }, { name: 'substitute', shortName: 's', possiblyAsync: true }, { name: 'nohlsearch', shortName: 'noh' }, + { name: 'yank', shortName: 'y' }, { name: 'delmarks', shortName: 'delm' }, { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, { name: 'global', shortName: 'g' } @@ -1072,6 +1082,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ function cmKey(key, cm) { if (!cm) { return undefined; } + if (this[key]) { return this[key]; } var vimKey = cmKeyToVimKey(key); if (!vimKey) { return false; @@ -1084,7 +1095,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'}; - var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del'}; + var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del',Insert:'Ins'}; function cmKeyToVimKey(key) { if (key.charAt(0) == '\'') { // Keypress character binding of format "'a'" @@ -1203,11 +1214,11 @@ dom.importCssString(".normal-mode .ace_cursor{\ cfg = cfg || {}; var scope = cfg.scope; if (!option) { - throw Error('Unknown option: ' + name); + return new Error('Unknown option: ' + name); } if (option.type == 'boolean') { if (value && value !== true) { - throw Error('Invalid argument: ' + name + '=' + value); + return new Error('Invalid argument: ' + name + '=' + value); } else if (value !== false) { // Boolean options are set to true if value is not defined. value = true; @@ -1235,7 +1246,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ cfg = cfg || {}; var scope = cfg.scope; if (!option) { - throw Error('Unknown option: ' + name); + return new Error('Unknown option: ' + name); } if (option.callback) { var local = cm && option.callback(undefined, cm); @@ -1438,7 +1449,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ jumpList: createCircularJumpList(), macroModeState: new MacroModeState, // Recording latest f, t, F or T motion command. - lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''}, + lastCharacterSearch: {increment:0, forward:true, selectedCharacter:''}, registerController: new RegisterController({}), // search history buffer searchHistoryController: new HistoryController(), @@ -1586,7 +1597,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } function handleKeyNonInsertMode() { - if (handleMacroRecording() || handleEsc()) { return true; }; + if (handleMacroRecording() || handleEsc()) { return true; } var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; if (/^[1-9]\d*$/.test(keys)) { return true; } @@ -1752,7 +1763,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ * for a reference implementation. */ function defineRegister(name, register) { - var registers = vimGlobalState.registerController.registers[name]; + var registers = vimGlobalState.registerController.registers; if (!name || name.length != 1) { throw Error('Register name must be 1 character'); } @@ -1778,9 +1789,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ } RegisterController.prototype = { pushText: function(registerName, operator, text, linewise, blockwise) { - if (linewise && text.charAt(0) == '\n') { - text = text.slice(1) + '\n'; - } if (linewise && text.charAt(text.length - 1) !== '\n'){ text += '\n'; } @@ -1848,7 +1856,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ }; function HistoryController() { this.historyBuffer = []; - this.iterator; + this.iterator = 0; this.initialPrefix = null; } HistoryController.prototype = { @@ -2014,9 +2022,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ var promptPrefix = (forward) ? '/' : '?'; var originalQuery = getSearchState(cm).getQuery(); var originalScrollPos = cm.getScrollInfo(); - originalScrollPos.cursor = cm.getCursor(); - if (getSearchState(cm).clearHighlight) // ace patch clear highlight after n - getSearchState(cm).clearHighlight(); function handleQuery(query, ignoreCase, smartCase) { vimGlobalState.searchHistoryController.pushInput(query); vimGlobalState.searchHistoryController.reset(); @@ -2032,28 +2037,23 @@ dom.importCssString(".normal-mode .ace_cursor{\ motion: 'findNext', motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist } }); - getSearchState(cm).clearHighlight = function clear() { - cm.off("cursorActivity", clear); - clearSearchHighlight(cm); - }; - cm.on("cursorActivity", getSearchState(cm).clearHighlight); } function onPromptClose(query) { cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - cm.setCursor(originalScrollPos.cursor); // ace patch TODO find a way to record motion without calling handleQuery - handleQuery(query, false /** ignoreCase */, false /** smartCase */); // ace patch TODO make smartcase an option + handleQuery(query, true /** ignoreCase */, true /** smartCase */); var macroModeState = vimGlobalState.macroModeState; if (macroModeState.isRecording) { logSearchQuery(macroModeState, query); } - clearSearchHighlight(cm); } function onPromptKeyUp(e, query, close) { - var keyName = CodeMirror.keyName(e), up; + var keyName = CodeMirror.keyName(e), up, offset; if (keyName == 'Up' || keyName == 'Down') { up = keyName == 'Up' ? true : false; + offset = e.target ? e.target.selectionEnd : 0; query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; close(query); + if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length); } else { if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') vimGlobalState.searchHistoryController.reset(); @@ -2061,17 +2061,15 @@ dom.importCssString(".normal-mode .ace_cursor{\ var parsedQuery; try { parsedQuery = updateSearchQuery(cm, query, - false /** ignoreCase */, false /** smartCase */); + true /** ignoreCase */, true /** smartCase */); } catch (e) { // Swallow bad regexes for incremental search. } if (parsedQuery) { - cm.scrollIntoView(findNext(cm, !forward, parsedQuery, undefined, originalScrollPos.cursor), 30); + cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); } else { - cm.scrollIntoView(originalScrollPos.cursor); clearSearchHighlight(cm); cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - cm.ace.curOp.command.scrollIntoView = "animate"; } } function onPromptKeyDown(e, query, close) { @@ -2087,6 +2085,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ clearInputState(cm); close(); cm.focus(); + } else if (keyName == 'Up' || keyName == 'Down') { + CodeMirror.e_stop(e); } else if (keyName == 'Ctrl-U') { // Ctrl-U clears input. CodeMirror.e_stop(e); @@ -2150,7 +2150,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ exCommandDispatcher.processCommand(cm, input); } function onPromptKeyDown(e, input, close) { - var keyName = CodeMirror.keyName(e), up; + var keyName = CodeMirror.keyName(e), up, offset; if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' || (keyName == 'Backspace' && input == '')) { vimGlobalState.exCommandHistoryController.pushInput(input); @@ -2161,9 +2161,12 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.focus(); } if (keyName == 'Up' || keyName == 'Down') { + CodeMirror.e_stop(e); up = keyName == 'Up' ? true : false; + offset = e.target ? e.target.selectionEnd : 0; input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; close(input); + if (offset && e.target) e.target.selectionEnd = e.target.selectionStart = Math.min(offset, e.target.value.length); } else if (keyName == 'Ctrl-U') { // Ctrl-U clears input. CodeMirror.e_stop(e); @@ -2179,7 +2182,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } else { if (vim.visualMode) { showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>', - onKeyDown: onPromptKeyDown}); + onKeyDown: onPromptKeyDown, selectValueOnOpen: false}); } else { showPrompt(cm, { onClose: onPromptClose, prefix: ':', onKeyDown: onPromptKeyDown}); @@ -2187,7 +2190,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } }, evalInput: function(cm, vim) { - // If the motion comand is set, execute both the operator and motion. + // If the motion command is set, execute both the operator and motion. // Otherwise return. var inputState = vim.inputState; var motion = inputState.motion; @@ -2428,9 +2431,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ return findNext(cm, prev/** prev */, query, motionArgs.repeat); }, goToMark: function(cm, _head, motionArgs, vim) { - var mark = vim.marks[motionArgs.selectedCharacter]; - if (mark) { - var pos = mark.find(); + var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter); + if (pos) { return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; } return null; @@ -2513,11 +2515,12 @@ dom.importCssString(".normal-mode .ace_cursor{\ var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; var first = cm.firstLine(); var last = cm.lastLine(); - // Vim cancels linewise motions that start on an edge and move beyond - // that edge. It does not cancel motions that do not start on an edge. - if ((line < first && cur.line == first) || - (line > last && cur.line == last)) { - return; + // Vim go to line begin or line end when cursor at first/last line and + // move to previous/next line is triggered. + if (line < first && cur.line == first){ + return this.moveToStartOfLine(cm, head, motionArgs, vim); + }else if (line > last && cur.line == last){ + return this.moveToEol(cm, head, motionArgs, vim); } // ace_patch{ var fold = cm.ace.session.getFoldLine(line); @@ -2736,7 +2739,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ }, repeatLastCharacterSearch: function(cm, head, motionArgs) { - var lastSearch = vimGlobalState.lastChararacterSearch; + var lastSearch = vimGlobalState.lastCharacterSearch; var repeat = motionArgs.repeat; var forward = motionArgs.forward === lastSearch.forward; var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); @@ -2847,7 +2850,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ vimGlobalState.registerController.pushText( args.registerName, 'delete', text, args.linewise, vim.visualBlock); - return clipCursorToContent(cm, finalHead); + var includeLineBreak = vim.insertMode + return clipCursorToContent(cm, finalHead, includeLineBreak); }, indent: function(cm, args, ranges) { var vim = cm.state.vim; @@ -3001,7 +3005,20 @@ dom.importCssString(".normal-mode .ace_cursor{\ enterMacroRecordMode: function(cm, actionArgs) { var macroModeState = vimGlobalState.macroModeState; var registerName = actionArgs.selectedCharacter; - macroModeState.enterMacroRecordMode(cm, registerName); + if (vimGlobalState.registerController.isValidRegister(registerName)) { + macroModeState.enterMacroRecordMode(cm, registerName); + } + }, + toggleOverwrite: function(cm) { + if (!cm.state.overwrite) { + cm.toggleOverwrite(true); + cm.setOption('keyMap', 'vim-replace'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); + } else { + cm.toggleOverwrite(false); + cm.setOption('keyMap', 'vim-insert'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); + } }, enterInsertMode: function(cm, actionArgs, vim) { if (cm.getOption('readOnly')) { return; } @@ -3048,7 +3065,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ return; } } - cm.setOption('keyMap', 'vim-insert'); cm.setOption('disableInput', false); if (actionArgs && actionArgs.replace) { // Handle Replace-mode as a special case of insert mode. @@ -3056,6 +3072,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.setOption('keyMap', 'vim-replace'); CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); } else { + cm.toggleOverwrite(false); cm.setOption('keyMap', 'vim-insert'); CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); } @@ -3392,25 +3409,32 @@ dom.importCssString(".normal-mode .ace_cursor{\ incrementNumberToken: function(cm, actionArgs) { var cur = cm.getCursor(); var lineStr = cm.getLine(cur.line); - var re = /-?\d+/g; + var re = /(-?)(?:(0x)([\da-f]+)|(0b|0|)(\d+))/gi; var match; var start; var end; var numberStr; - var token; while ((match = re.exec(lineStr)) !== null) { - token = match[0]; start = match.index; - end = start + token.length; + end = start + match[0].length; if (cur.ch < end)break; } if (!actionArgs.backtrack && (end <= cur.ch))return; - if (token) { + if (match) { + var baseStr = match[2] || match[4] + var digits = match[3] || match[5] var increment = actionArgs.increase ? 1 : -1; - var number = parseInt(token) + (increment * actionArgs.repeat); + var base = {'0b': 2, '0': 8, '': 10, '0x': 16}[baseStr.toLowerCase()]; + var number = parseInt(match[1] + digits, base) + (increment * actionArgs.repeat); + numberStr = number.toString(base); + var zeroPadding = baseStr ? new Array(digits.length - numberStr.length + 1 + match[1].length).join('0') : '' + if (numberStr.charAt(0) === '-') { + numberStr = '-' + baseStr + zeroPadding + numberStr.substr(1); + } else { + numberStr = baseStr + zeroPadding + numberStr; + } var from = Pos(cur.line, start); var to = Pos(cur.line, end); - numberStr = number.toString(); cm.replaceRange(numberStr, from, to); } else { return; @@ -3428,6 +3452,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ } repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); }, + indent: function(cm, actionArgs) { + cm.indentLine(cm.getCursor().line, actionArgs.indentRight); + }, exitInsertMode: exitInsertMode }; @@ -3505,7 +3532,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } } function lastChar(keys) { - var match = /^.*(<[\w\-]+>)$/.exec(keys); + var match = /^.*(<[^>]+>)$/.exec(keys); var selectedCharacter = match ? match[1] : keys.slice(-1); if (selectedCharacter.length > 1){ switch(selectedCharacter){ @@ -3516,6 +3543,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ selectedCharacter=' '; break; default: + selectedCharacter=''; break; } } @@ -3616,7 +3644,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; selections.push(range); } - primIndex = head.line == lastLine ? selections.length - 1 : 0; cm.setSelections(selections); selectionEnd.ch = headCh; base.ch = baseCh; @@ -3832,7 +3859,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ // Only clip if the selection ends with trailing newline + whitespace if (/\n\s*$/.test(selection)) { var lines = selection.split('\n'); - // We know this is all whitepsace. + // We know this is all whitespace. lines.pop(); // Cases: @@ -3918,9 +3945,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ } function recordLastCharacterSearch(increment, args) { - vimGlobalState.lastChararacterSearch.increment = increment; - vimGlobalState.lastChararacterSearch.forward = args.forward; - vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter; + vimGlobalState.lastCharacterSearch.increment = increment; + vimGlobalState.lastCharacterSearch.forward = args.forward; + vimGlobalState.lastCharacterSearch.selectedCharacter = args.selectedCharacter; } var symbolToMode = { @@ -4044,7 +4071,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ return cur; } - /** + /* * Returns the boundaries of the next word. If the cursor in the middle of * the word, then returns the boundaries of the current word, starting at * the cursor. If the cursor is at the start/end of a word, and we are going @@ -4119,8 +4146,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ line = cm.getLine(lineNum); pos = (dir > 0) ? 0 : line.length; } - // Should never get here. - throw new Error('The impossible happened.'); } /** @@ -4291,7 +4316,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } // TODO: perhaps this finagling of start and end positions belonds - // in codmirror/replaceRange? + // in codemirror/replaceRange? function selectCompanionObject(cm, head, symb, inclusive) { var cur = head, start, end; @@ -4432,7 +4457,10 @@ dom.importCssString(".normal-mode .ace_cursor{\ if (cm.openDialog) { cm.openDialog(template, onClose, { bottom: true, value: options.value, onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp, - selectValueOnOpen: false}); + selectValueOnOpen: false, onClose: function() { + cm.state.vim.status = ""; + cm.ace.renderer.$loop.schedule(cm.ace.renderer.CHANGE_CURSOR); + }}); } else { onClose(prompt(shortText, '')); @@ -4634,7 +4662,11 @@ dom.importCssString(".normal-mode .ace_cursor{\ } } function makePrompt(prefix, desc) { - return prefix; + var raw = '' + + (prefix || "") + ''; + if (desc) + raw += ' ' + desc + ''; + return raw; } var searchPromptDesc = '(Javascript regexp)'; function showPrompt(cm, options) { @@ -4726,10 +4758,10 @@ dom.importCssString(".normal-mode .ace_cursor{\ searchState.setOverlay(overlay); } } - function findNext(cm, prev, query, repeat, startPos) { + function findNext(cm, prev, query, repeat) { if (repeat === undefined) { repeat = 1; } return cm.operation(function() { - var pos = startPos || cm.getCursor(); + var pos = cm.getCursor(); var cursor = cm.getSearchCursor(query, pos); for (var i = 0; i < repeat; i++) { var found = cursor.find(prev); @@ -4792,6 +4824,28 @@ dom.importCssString(".normal-mode .ace_cursor{\ // ace_patch} } + function getMarkPos(cm, vim, markName) { + /* TODO reenable when selection history in ace is implemented + if (markName == '\'') { + var history = cm.doc.history.done; + var event = history[history.length - 2]; + return event && event.ranges && event.ranges[0].head; + } else if (markName == '.') { + if (cm.doc.history.lastModTime == 0) { + return // If no changes, bail out; don't bother to copy or reverse history array. + } else { + var changeHistory = cm.doc.history.done.filter(function(el){ if (el.changes !== undefined) { return el } }); + changeHistory.reverse(); + var lastEditPos = changeHistory[0].changes[0].to; + } + return lastEditPos; + } + */ + + var mark = vim.marks[markName]; + return mark && mark.find(); + } + var ExCommandDispatcher = function() { this.buildCommandMap_(); }; @@ -4875,7 +4929,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } else { result.line = this.parseLineSpec_(cm, inputStream); if (result.line !== undefined && inputStream.eat(',')) { - result.lineEnd = this.parseLineSpec_(cm, inputStream, result.line); + result.lineEnd = this.parseLineSpec_(cm, inputStream); } } @@ -4889,35 +4943,45 @@ dom.importCssString(".normal-mode .ace_cursor{\ return result; }, - parseLineSpec_: function(cm, inputStream, prevLine) { + parseLineSpec_: function(cm, inputStream) { var numberMatch = inputStream.match(/^(\d+)/); if (numberMatch) { + // Absolute line number plus offset (N+M or N-M) is probably a typo, + // not something the user actually wanted. (NB: vim does allow this.) return parseInt(numberMatch[1], 10) - 1; } switch (inputStream.next()) { case '.': - return cm.getCursor().line; + return this.parseLineSpecOffset_(inputStream, cm.getCursor().line); case '$': - return cm.lastLine(); + return this.parseLineSpecOffset_(inputStream, cm.lastLine()); case '\'': - var mark = cm.state.vim.marks[inputStream.next()]; - if (mark && mark.find()) { - return mark.find().line; - } - throw new Error('Mark not set'); + var markName = inputStream.next(); + var markPos = getMarkPos(cm, cm.state.vim, markName); + if (!markPos) throw new Error('Mark not set'); + return this.parseLineSpecOffset_(inputStream, markPos.line); + case '-': case '+': - if (prevLine) { - var match = inputStream.match(/^\d+/); - if (match) { - return prevLine + parseInt(match[0], 10); - } - } - throw new Error('Require prevLine'); + inputStream.backUp(1); + // Offset is relative to current line if not otherwise specified. + return this.parseLineSpecOffset_(inputStream, cm.getCursor().line); default: inputStream.backUp(1); return undefined; } }, + parseLineSpecOffset_: function(inputStream, line) { + var offsetMatch = inputStream.match(/^([+-])?(\d+)/); + if (offsetMatch) { + var offset = parseInt(offsetMatch[2], 10); + if (offsetMatch[1] == "-") { + line -= offset; + } else { + line += offset; + } + } + return line; + }, parseCommandArgs_: function(inputStream, params, command) { if (inputStream.eol()) { return; @@ -4981,8 +5045,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ var mapping = { keys: lhs, type: 'keyToEx', - exArgs: { input: rhs.substring(1) }, - user: true}; + exArgs: { input: rhs.substring(1) } + }; if (ctx) { mapping.context = ctx; } defaultKeymap.unshift(mapping); } else { @@ -4990,8 +5054,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ var mapping = { keys: lhs, type: 'keyToKey', - toKeys: rhs, - user: true + toKeys: rhs }; if (ctx) { mapping.context = ctx; } defaultKeymap.unshift(mapping); @@ -5012,14 +5075,13 @@ dom.importCssString(".normal-mode .ace_cursor{\ var keys = lhs; for (var i = 0; i < defaultKeymap.length; i++) { if (keys == defaultKeymap[i].keys - && defaultKeymap[i].context === ctx - && defaultKeymap[i].user) { + && defaultKeymap[i].context === ctx) { defaultKeymap.splice(i, 1); return; } } } - // throw Error('No such mapping.'); + // ace_patch } }; @@ -5099,13 +5161,18 @@ dom.importCssString(".normal-mode .ace_cursor{\ // If no value is provided, then we assume this is a get. if (!optionIsBoolean && value === undefined || forceGet) { var oldValue = getOption(optionName, cm, setCfg); - if (oldValue === true || oldValue === false) { + if (oldValue instanceof Error) { + showConfirm(cm, oldValue.message); + } else if (oldValue === true || oldValue === false) { showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName); } else { showConfirm(cm, ' ' + optionName + '=' + oldValue); } } else { - setOption(optionName, value, cm, setCfg); + var setOptionReturn = setOption(optionName, value, cm, setCfg); + if (setOptionReturn instanceof Error) { + showConfirm(cm, setOptionReturn.message); + } } }, setlocal: function (cm, params) { @@ -5144,25 +5211,27 @@ dom.importCssString(".normal-mode .ace_cursor{\ showConfirm(cm, regInfo); }, sort: function(cm, params) { - var reverse, ignoreCase, unique, number; + var reverse, ignoreCase, unique, number, pattern; function parseArgs() { if (params.argString) { var args = new CodeMirror.StringStream(params.argString); if (args.eat('!')) { reverse = true; } if (args.eol()) { return; } if (!args.eatSpace()) { return 'Invalid arguments'; } - var opts = args.match(/[a-z]+/); - if (opts) { - opts = opts[0]; - ignoreCase = opts.indexOf('i') != -1; - unique = opts.indexOf('u') != -1; - var decimal = opts.indexOf('d') != -1 && 1; - var hex = opts.indexOf('x') != -1 && 1; - var octal = opts.indexOf('o') != -1 && 1; + var opts = args.match(/([dinuox]+)?\s*(\/.+\/)?\s*/); + if (!opts && !args.eol()) { return 'Invalid arguments'; } + if (opts[1]) { + ignoreCase = opts[1].indexOf('i') != -1; + unique = opts[1].indexOf('u') != -1; + var decimal = opts[1].indexOf('d') != -1 || opts[1].indexOf('n') != -1 && 1; + var hex = opts[1].indexOf('x') != -1 && 1; + var octal = opts[1].indexOf('o') != -1 && 1; if (decimal + hex + octal > 1) { return 'Invalid arguments'; } number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; } - if (args.match(/\/.*\//)) { return 'patterns not supported'; } + if (opts[2]) { + pattern = new RegExp(opts[2].substr(1, opts[2].length - 2), ignoreCase ? 'i' : ''); + } } } var err = parseArgs(); @@ -5176,14 +5245,18 @@ dom.importCssString(".normal-mode .ace_cursor{\ var curStart = Pos(lineStart, 0); var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); var text = cm.getRange(curStart, curEnd).split('\n'); - var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ : + var numberRegex = pattern ? pattern : + (number == 'decimal') ? /(-?)([\d]+)/ : (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : (number == 'octal') ? /([0-7]+)/ : null; var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; var numPart = [], textPart = []; - if (number) { + if (number || pattern) { for (var i = 0; i < text.length; i++) { - if (numberRegex.exec(text[i])) { + var matchPart = pattern ? text[i].match(pattern) : null; + if (matchPart && matchPart[0] != '') { + numPart.push(matchPart); + } else if (!pattern && numberRegex.exec(text[i])) { numPart.push(text[i]); } else { textPart.push(text[i]); @@ -5202,8 +5275,17 @@ dom.importCssString(".normal-mode .ace_cursor{\ bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); return anum - bnum; } - numPart.sort(compareFn); - textPart.sort(compareFn); + function comparePatternFn(a, b) { + if (reverse) { var tmp; tmp = a; a = b; b = tmp; } + if (ignoreCase) { a[0] = a[0].toLowerCase(); b[0] = b[0].toLowerCase(); } + return (a[0] < b[0]) ? -1 : 1; + } + numPart.sort(pattern ? comparePatternFn : compareFn); + if (pattern) { + for (var i = 0; i < numPart.length; i++) { + numPart[i] = numPart[i].input; + } + } else if (!number) { textPart.sort(compareFn); } text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); if (unique) { // Remove duplicate lines var textOld = text; @@ -5289,6 +5371,10 @@ dom.importCssString(".normal-mode .ace_cursor{\ if (tokens.length) { regexPart = tokens[0]; replacePart = tokens[1]; + if (regexPart && regexPart[regexPart.length - 1] === '$') { + regexPart = regexPart.slice(0, regexPart.length - 1) + '\\n'; + replacePart = replacePart ? replacePart + '\n' : '\n'; + } if (replacePart !== undefined) { if (getOption('pcre')) { replacePart = unescapeRegexReplace(replacePart); @@ -5322,7 +5408,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ global = true; flagsPart.replace('g', ''); } - regexPart = regexPart + '/' + flagsPart; + regexPart = regexPart.replace(/\//g, "\\/") + '/' + flagsPart; } } if (regexPart) { @@ -5362,14 +5448,21 @@ dom.importCssString(".normal-mode .ace_cursor{\ if (CodeMirror.commands.save) { // If a save command is defined, call it. CodeMirror.commands.save(cm); - } else { - // Saves to text area if no save command is defined. + } else if (cm.save) { + // Saves to text area if no save command is defined and cm.save() is available. cm.save(); } }, nohlsearch: function(cm) { clearSearchHighlight(cm); }, + yank: function (cm) { + var cur = copyCursor(cm.getCursor()); + var line = cur.line; + var lineText = cm.getLine(line); + vimGlobalState.registerController.pushText( + '0', 'yank', lineText, true, true); + }, delmarks: function(cm, params) { if (!params.argString || !trim(params.argString)) { showConfirm(cm, 'Argument required'); @@ -5531,7 +5624,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ } if (!confirm) { replaceAll(); - if (callback) { callback(); }; + if (callback) { callback(); } return; } showPrompt(cm, { @@ -5557,7 +5650,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ // so as to update the ". register as expected in real vim. var text = []; if (!isPlaying) { - var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1; + var selLength = lastChange.inVisualBlock && vim.lastSelection ? + vim.lastSelection.visualBlock.height : 1; var changes = lastChange.changes; var text = []; var i = 0; @@ -5591,8 +5685,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1); cm.setOption('keyMap', 'vim'); cm.setOption('disableInput', true); - - lastChange.overwrite = cm.state.overwrite; cm.toggleOverwrite(false); // exit replace mode if we were in it. // update the ". register before exiting insert mode insertModeChangeRegister.setText(lastChange.changes.join('')); @@ -5675,7 +5767,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ exitInsertMode(cm); } } - }; + } macroModeState.isPlaying = false; } @@ -5710,7 +5802,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ * Listens for changes made in insert mode. * Should only be active in insert mode. */ - function onChange(_cm, changeObj) { + function onChange(cm, changeObj) { var macroModeState = vimGlobalState.macroModeState; var lastChange = macroModeState.lastInsertModeChanges; if (!macroModeState.isPlaying) { @@ -5723,7 +5815,11 @@ dom.importCssString(".normal-mode .ace_cursor{\ lastChange.changes = []; lastChange.maybeReset = false; } - lastChange.changes.push(text); + if (cm.state.overwrite && !/\n/.test(text)) { + lastChange.changes.push([text]); + } else { + lastChange.changes.push(text); + } } // Change objects may be chained with next. changeObj = changeObj.next; @@ -5848,7 +5944,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ // insert mode changes. Will conform to that behavior. repeat = !vim.lastEditActionCommand ? 1 : repeat; var changeObject = macroModeState.lastInsertModeChanges; - repeatInsertModeChanges(cm, changeObject.changes, repeat, changeObject.overwrite); + repeatInsertModeChanges(cm, changeObject.changes, repeat); } } vim.inputState = vim.lastEditInputState; @@ -5875,9 +5971,9 @@ dom.importCssString(".normal-mode .ace_cursor{\ exitInsertMode(cm); } macroModeState.isPlaying = false; - }; + } - function repeatInsertModeChanges(cm, changes, repeat, overwrite) { + function repeatInsertModeChanges(cm, changes, repeat) { function keyHandler(binding) { if (typeof binding == 'string') { CodeMirror.commands[binding](cm); @@ -5905,13 +6001,13 @@ dom.importCssString(".normal-mode .ace_cursor{\ var change = changes[j]; if (change instanceof InsertModeKey) { CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); - } else { + } else if (typeof change == "string") { var cur = cm.getCursor(); - var end = cur; - if (overwrite && !/\n/.test(change)) { - end = offsetCursor(cur, 0, change.length); - } - cm.replaceRange(change, cur, end); + cm.replaceRange(change, cur, cur); + } else { + var start = cm.getCursor(); + var end = offsetCursor(start, 0, change[0].length); + cm.replaceRange(change[0], start, end); } } } @@ -6042,6 +6138,38 @@ dom.importCssString(".normal-mode .ace_cursor{\ var vim = getVim(cm); if (keyCode == -1) return; + // in non-insert mode we try to find the ascii key corresponding to the text in textarea + // this is needed because in languages that use latin alphabet we want to get the key that browser sends to the textarea + // and in non + if (!vim.insertMode) { + if (hashId == -1) { + if (key.charCodeAt(0) > 0xFF) { + if (data.inputKey) { + key = data.inputKey; + if (key && data.inputHash == 4) + key = key.toUpperCase(); + } + } + data.inputChar = key; + } + else if (hashId == 4 || hashId == 0) { + if (data.inputKey == key && data.inputHash == hashId && data.inputChar) { + // on mac text input doesn't repeat + key = data.inputChar; + hashId = -1 + } + else { + data.inputChar = null; + data.inputKey = key; + data.inputHash = hashId; + } + } + else { + data.inputChar = data.inputKey = null; + } + } + + // ctrl-c is special it both exits mode and copies text if (key == "c" && hashId == 1) { // key == "ctrl-c" if (!useragent.isMac && editor.getCopyText()) { editor.once("copy", function() { @@ -6049,11 +6177,12 @@ dom.importCssString(".normal-mode .ace_cursor{\ }); return {command: "null", passEvent: true}; } - } else if (!vim.insertMode) { - if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) { - hashId = -1; - key = data.inputChar; - } + } + + if (key == "esc" && !vim.insertMode && !vim.visualMode && !cm.ace.inMultiSelectMode) { + var searchState = getSearchState(cm); + var overlay = searchState.getOverlay(); + if (overlay) cm.removeOverlay(overlay); } if (hashId == -1 || hashId & 1 || hashId === 0 && key.length > 1) { @@ -6092,12 +6221,19 @@ dom.importCssString(".normal-mode .ace_cursor{\ }); cm.on("vim-mode-change", function() { if (cm.virtualSelectionMode()) return; - cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); + updateInputMode(); cm._signal("changeStatus"); }); - cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); + function updateInputMode() { + var isIntsert = getVim(cm).insertMode; + cm.ace.renderer.setStyle("normal-mode", !isIntsert); + editor.textInput.setCommandMode(!isIntsert); + // without this press and hodl popup in mac is shown in normal mode + editor.renderer.$keepTextAreaAtCursor = isIntsert; + editor.renderer.$blockCursor = !isIntsert; + } + updateInputMode(); editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(cm); - // renderVirtualNumbers.attach(editor); this.updateMacCompositionHandlers(editor, true); }, detach: function(editor) { @@ -6108,7 +6244,8 @@ dom.importCssString(".normal-mode .ace_cursor{\ editor.$vimModeHandler = null; editor.renderer.$cursorLayer.drawCursor = null; editor.renderer.setStyle("normal-mode", false); - // renderVirtualNumbers.detach(editor); + editor.textInput.setCommandMode(false); + editor.renderer.$keepTextAreaAtCursor = true; this.updateMacCompositionHandlers(editor, false); }, getStatusText: function(editor) { @@ -6128,27 +6265,6 @@ dom.importCssString(".normal-mode .ace_cursor{\ status += (status ? " " : "") + vim.status; return status; }, - // workaround for j not repeating with `defaults write -g ApplePressAndHoldEnabled -bool true` - handleMacRepeat: function(data, hashId, key) { - if (hashId == -1) { - // record key - data.inputChar = key; - data.lastEvent = "input"; - } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) { - // check for repeated keypress - if (data.lastEvent == "input") { - data.lastEvent = "input1"; - } else if (data.lastEvent == "input1") { - // simulate textinput - return true; - } - } else { - // reset - data.$lastHash = hashId; - data.$lastKey = key; - data.lastEvent = "keypress"; - } - }, // on mac, with some keyboard layouts (e.g swedish) ^ starts composition, we don't need it in normal mode updateMacCompositionHandlers: function(editor, enable) { var onCompositionUpdateOverride = function(text) { @@ -6166,7 +6282,7 @@ dom.importCssString(".normal-mode .ace_cursor{\ var onCompositionStartOverride = function(text) { var cm = editor.state.cm; var vim = getVim(cm); - if (!vim.insertMode) { + if (vim.insertMode) { this.onCompositionStartOrig(text); } }; diff --git a/plugins/node_modules/ace/lib/ace/keyboard/vim_test.js b/plugins/node_modules/ace/lib/ace/keyboard/vim_test.js index 0791d65e..3a9ead85 100644 --- a/plugins/node_modules/ace/lib/ace/keyboard/vim_test.js +++ b/plugins/node_modules/ace/lib/ace/keyboard/vim_test.js @@ -14,6 +14,7 @@ var VirtualRenderer = require("./../virtual_renderer").VirtualRenderer; var assert = require("./../test/assertions"); var keys = require("./../lib/keys"); var vim = require("./vim"); +var isAce = true; var el = document.createElement("div"); el.style.position = "fixed"; @@ -23,8 +24,7 @@ el.style.width = "500px"; el.style.height = "300px"; document.body.appendChild(el); -if (window.name == "nodejs") - return console.log("Skipping test: This test only runs in the browser"); +var phantom = window.name == "nodejs"; var renderer = new VirtualRenderer(el); editor = new Editor(renderer);//(new MockRenderer()); @@ -73,11 +73,14 @@ function test(name, fn) { else exports["test " + name] = fn; } -function expectFail(fn) { +function expectFail(fn, silent) { try { fn(); - } catch(expected) {}; - throw new Error("Expected to throw an error"); + } catch(expected) { + return; + }; + if (!silent) + throw new Error("Expected to throw an error"); } vim.CodeMirror.Vim.unmap("Y"); @@ -91,10 +94,10 @@ vim.CodeMirror.Vim.defineEx('write', 'w', function(cm) { // cm.setBookmark({ch: 4, line: 0}) // cm.replaceRange("x-", {ch: 4, line: 0}, {ch: 5, line: 0}); [editor.$vimModeHandler.cm.marks[0].find(),editor.$vimModeHandler.cm.marks[1].find()] -var lineText, verbose, phantom; +var lineText, verbose; var Pos = CodeMirror.Pos; var place = document.createElement("div"); -var eqPos = assert.deepEqual; +var eqCursorPos = assert.deepEqual; var eq = assert.equal; var is = assert.ok; @@ -139,63 +142,63 @@ var bracesLine = lines[3]; var seekBraceLine = lines[4]; var word1 = { - start: { line: wordLine.line, ch: 1 }, - end: { line: wordLine.line, ch: 5 } + start: new Pos(wordLine.line, 1), + end: new Pos(wordLine.line, 5) }; var word2 = { - start: { line: wordLine.line, ch: word1.end.ch + 2 }, - end: { line: wordLine.line, ch: word1.end.ch + 4 } + start: new Pos(wordLine.line, word1.end.ch + 2), + end: new Pos(wordLine.line, word1.end.ch + 4) }; var word3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 5 } + start: new Pos(bigWordLine.line, 1), + end: new Pos(bigWordLine.line, 5) }; var bigWord1 = word1; var bigWord2 = word2; var bigWord3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 7 } + start: new Pos(bigWordLine.line, 1), + end: new Pos(bigWordLine.line, 7) }; var bigWord4 = { - start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 }, - end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 } + start: new Pos(bigWordLine.line, bigWord1.end.ch + 3), + end: new Pos(bigWordLine.line, bigWord1.end.ch + 7) }; -var oChars = [ { line: charLine.line, ch: 1 }, - { line: charLine.line, ch: 3 }, - { line: charLine.line, ch: 7 } ]; -var pChars = [ { line: charLine.line, ch: 2 }, - { line: charLine.line, ch: 4 }, - { line: charLine.line, ch: 6 }, - { line: charLine.line, ch: 8 } ]; -var numChars = [ { line: charLine.line, ch: 10 }, - { line: charLine.line, ch: 12 }, - { line: charLine.line, ch: 14 }, - { line: charLine.line, ch: 16 }, - { line: charLine.line, ch: 18 }]; +var oChars = [ new Pos(charLine.line, 1), + new Pos(charLine.line, 3), + new Pos(charLine.line, 7) ]; +var pChars = [ new Pos(charLine.line, 2), + new Pos(charLine.line, 4), + new Pos(charLine.line, 6), + new Pos(charLine.line, 8) ]; +var numChars = [ new Pos(charLine.line, 10), + new Pos(charLine.line, 12), + new Pos(charLine.line, 14), + new Pos(charLine.line, 16), + new Pos(charLine.line, 18)]; var parens1 = { - start: { line: bracesLine.line, ch: 1 }, - end: { line: bracesLine.line, ch: 3 } + start: new Pos(bracesLine.line, 1), + end: new Pos(bracesLine.line, 3) }; var squares1 = { - start: { line: bracesLine.line, ch: 5 }, - end: { line: bracesLine.line, ch: 7 } + start: new Pos(bracesLine.line, 5), + end: new Pos(bracesLine.line, 7) }; var curlys1 = { - start: { line: bracesLine.line, ch: 9 }, - end: { line: bracesLine.line, ch: 11 } + start: new Pos(bracesLine.line, 9), + end: new Pos(bracesLine.line, 11) }; var seekOutside = { - start: { line: seekBraceLine.line, ch: 1 }, - end: { line: seekBraceLine.line, ch: 16 } + start: new Pos(seekBraceLine.line, 1), + end: new Pos(seekBraceLine.line, 16) }; var seekInside = { - start: { line: seekBraceLine.line, ch: 14 }, - end: { line: seekBraceLine.line, ch: 11 } + start: new Pos(seekBraceLine.line, 14), + end: new Pos(seekBraceLine.line, 11) }; function copyCursor(cur) { - return { ch: cur.ch, line: cur.line }; + return new Pos(cur.line, cur.ch); } function forEach(arr, func) { @@ -248,7 +251,7 @@ function testVim(name, run, opts, expectedFail) { for (var i = 0; i < arguments.length; i++) { var key = arguments[i]; // Find key in keymap and handle. - var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler); + var handled = CodeMirror.lookupKey(key, cm.getOption('keyMap'), executeHandler, cm); // Record for insert mode. if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; @@ -273,7 +276,7 @@ function testVim(name, run, opts, expectedFail) { } else { pos = makeCursor(line, ch); } - eqPos(pos, cm.getCursor()); + eqCursorPos(cm.getCursor(), pos); } } function fakeOpenDialog(result) { @@ -372,10 +375,10 @@ testJumplist('jumplist_repeat_', ['*', '*', '*', '3', '', '2', '' testJumplist('jumplist_repeated_motion', ['3', '*', ''], [2,3], [2,3]); testJumplist('jumplist_/', ['/', ''], [2,3], [2,3], 'dialog'); testJumplist('jumplist_?', ['?', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_skip_delted_mark', +testJumplist('jumplist_skip_deleted_mark', ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], [0,2], [0,2]); -testJumplist('jumplist_skip_delted_mark', +testJumplist('jumplist_skip_deleted_mark', ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], [1,0], [0,2]); @@ -388,7 +391,7 @@ testJumplist('jumplist_skip_delted_mark', function testMotion(name, keys, endPos, startPos) { testVim(name, function(cm, vim, helpers) { if (!startPos) { - startPos = { line: 0, ch: 0 }; + startPos = new Pos(0, 0); } cm.setCursor(startPos); helpers.doKeys(keys); @@ -397,11 +400,11 @@ function testMotion(name, keys, endPos, startPos) { } function makeCursor(line, ch) { - return { line: line, ch: ch }; + return new Pos(line, ch); } function offsetCursor(cur, offsetLine, offsetCh) { - return { line: cur.line + offsetLine, ch: cur.ch + offsetCh }; + return new Pos(cur.line + offsetLine, cur.ch + offsetCh); } // Motion tests @@ -504,20 +507,20 @@ testVim('Changing lines after Eol operation', function(cm, vim, helpers) { helpers.doKeys(['$']); helpers.doKeys(['j']); // After moving to Eol and then down, we should be at Eol of line 2 - helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 }); + helpers.assertCursorAt(new Pos(1, lines[1].length - 1)); helpers.doKeys(['j']); // After moving down, we should be at Eol of line 3 - helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 }); + helpers.assertCursorAt(new Pos(2, lines[2].length - 1)); helpers.doKeys(['h']); helpers.doKeys(['j']); // After moving back one space and then down, since line 4 is shorter than line 2, we should // be at Eol of line 2 - 1 - helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 }); + helpers.assertCursorAt(new Pos(3, lines[3].length - 1)); helpers.doKeys(['j']); helpers.doKeys(['j']); // After moving down again, since line 3 has enough characters, we should be back to the // same place we were at on line 1 - helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 }); + helpers.assertCursorAt(new Pos(5, lines[2].length - 2)); }); //making sure gj and gk recover from clipping testVim('gj_gk_clipping', function(cm,vim,helpers){ @@ -529,6 +532,7 @@ testVim('gj_gk_clipping', function(cm,vim,helpers){ },{value: 'line 1\n\nline 2'}); //testing a mix of j/k and gj/gk testVim('j_k_and_gj_gk', function(cm,vim,helpers){ + if (phantom) return; cm.setSize(120); cm.setCursor(0, 0); //go to the last character on the first line @@ -566,7 +570,7 @@ testVim('gj_gk', function(cm, vim, helpers) { // Test moving down preserves column position. helpers.doKeys('g', 'j'); var pos1 = cm.getCursor(); - var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4}; + var expectedPos2 = new Pos(0, (pos1.ch - 4) * 2 + 4); helpers.doKeys('g', 'j'); helpers.assertCursorAt(expectedPos2); @@ -581,7 +585,7 @@ testVim('gj_gk', function(cm, vim, helpers) { var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); var endingCharCoords = cm.charCoords(endingPos); is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); -},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' }); +},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentionallylongtotestmovementofgjandgkoverwrappedlines.' }); testVim('}', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doKeys('}'); @@ -626,14 +630,14 @@ testVim('paragraph_motions', function(cm, vim, helpers) { // ip inside empty space cm.setCursor(10, 0); helpers.doKeys('v', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(12, 0), cm.getCursor('head')); + eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); + eqCursorPos(Pos(12, 0), cm.getCursor('head')); helpers.doKeys('i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); + eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); + eqCursorPos(Pos(13, 1), cm.getCursor('head')); helpers.doKeys('2', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); + eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); + eqCursorPos(Pos(16, 1), cm.getCursor('head')); // should switch to visualLine mode cm.setCursor(14, 0); @@ -642,31 +646,31 @@ testVim('paragraph_motions', function(cm, vim, helpers) { cm.setCursor(14, 0); helpers.doKeys('', 'V', 'i', 'p'); - eqPos(Pos(16, 1), cm.getCursor('head')); + eqCursorPos(Pos(16, 1), cm.getCursor('head')); // ap inside empty space cm.setCursor(10, 0); helpers.doKeys('', 'v', 'a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); + eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); + eqCursorPos(Pos(13, 1), cm.getCursor('head')); helpers.doKeys('a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); + eqCursorPos(Pos(7, 0), cm.getCursor('anchor')); + eqCursorPos(Pos(16, 1), cm.getCursor('head')); cm.setCursor(13, 0); helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(13, 0), cm.getCursor('anchor')); - eqPos(Pos(14, 0), cm.getCursor('head')); + eqCursorPos(Pos(13, 0), cm.getCursor('anchor')); + eqCursorPos(Pos(14, 0), cm.getCursor('head')); cm.setCursor(16, 0); helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(14, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); + eqCursorPos(Pos(14, 0), cm.getCursor('anchor')); + eqCursorPos(Pos(16, 1), cm.getCursor('head')); cm.setCursor(0, 0); helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(0, 0), cm.getCursor('anchor')); - eqPos(Pos(4, 0), cm.getCursor('head')); + eqCursorPos(Pos(0, 0), cm.getCursor('anchor')); + eqCursorPos(Pos(4, 0), cm.getCursor('head')); cm.setCursor(0, 0); helpers.doKeys('d', 'i', 'p'); @@ -688,7 +692,7 @@ testVim('dl', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq(' ', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); }, { value: ' word1 ' }); testVim('dl_eol', function(cm, vim, helpers) { cm.setCursor(0, 6); @@ -707,7 +711,7 @@ testVim('dl_repeat', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq(' w', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); }, { value: ' word1 ' }); testVim('dh', function(cm, vim, helpers) { var curStart = makeCursor(0, 3); @@ -717,7 +721,7 @@ testVim('dh', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq('o', register.toString()); is(!register.linewise); - eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); + eqCursorPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); }, { value: ' word1 ' }); testVim('dj', function(cm, vim, helpers) { var curStart = makeCursor(0, 3); @@ -733,11 +737,11 @@ testVim('dj_end_of_document', function(cm, vim, helpers) { var curStart = makeCursor(0, 3); cm.setCursor(curStart); helpers.doKeys('d', 'j'); - eq(' word1 ', cm.getValue()); + eq('', cm.getValue()); var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); + eq(' word1 \n', register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, 0); }, { value: ' word1 ' }); testVim('dk', function(cm, vim, helpers) { var curStart = makeCursor(1, 3); @@ -753,11 +757,11 @@ testVim('dk_start_of_document', function(cm, vim, helpers) { var curStart = makeCursor(0, 3); cm.setCursor(curStart); helpers.doKeys('d', 'k'); - eq(' word1 ', cm.getValue()); + eq('', cm.getValue()); var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); + eq(' word1 \n', register.toString()); + is(register.linewise); + helpers.assertCursorAt(0, 0); }, { value: ' word1 ' }); testVim('dw_space', function(cm, vim, helpers) { var curStart = makeCursor(0, 0); @@ -767,7 +771,7 @@ testVim('dw_space', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq(' ', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); }, { value: ' word1 ' }); testVim('dw_word', function(cm, vim, helpers) { var curStart = makeCursor(0, 1); @@ -777,7 +781,7 @@ testVim('dw_word', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq('word1 ', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); }, { value: ' word1 word2' }); testVim('dw_unicode_word', function(cm, vim, helpers) { helpers.doKeys('d', 'w'); @@ -947,7 +951,7 @@ testVim('d_inclusive', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq('word1', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); }, { value: ' word1 ' }); testVim('d_reverse', function(cm, vim, helpers) { // Test that deleting in reverse works. @@ -961,8 +965,8 @@ testVim('d_reverse', function(cm, vim, helpers) { }, { value: ' word1\nword2 ' }); testVim('dd', function(cm, vim, helpers) { cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 1, ch: 0 }); + var expectedBuffer = cm.getRange(new Pos(0, 0), + new Pos(1, 0)); var expectedLineCount = cm.lineCount() - 1; helpers.doKeys('d', 'd'); eq(expectedLineCount, cm.lineCount()); @@ -973,8 +977,8 @@ testVim('dd', function(cm, vim, helpers) { }); testVim('dd_prefix_repeat', function(cm, vim, helpers) { cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); + var expectedBuffer = cm.getRange(new Pos(0, 0), + new Pos(2, 0)); var expectedLineCount = cm.lineCount() - 2; helpers.doKeys('2', 'd', 'd'); eq(expectedLineCount, cm.lineCount()); @@ -985,8 +989,8 @@ testVim('dd_prefix_repeat', function(cm, vim, helpers) { }); testVim('dd_motion_repeat', function(cm, vim, helpers) { cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); + var expectedBuffer = cm.getRange(new Pos(0, 0), + new Pos(2, 0)); var expectedLineCount = cm.lineCount() - 2; helpers.doKeys('d', '2', 'd'); eq(expectedLineCount, cm.lineCount()); @@ -997,8 +1001,8 @@ testVim('dd_motion_repeat', function(cm, vim, helpers) { }); testVim('dd_multiply_repeat', function(cm, vim, helpers) { cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); + var expectedBuffer = cm.getRange(new Pos(0, 0), + new Pos(6, 0)); var expectedLineCount = cm.lineCount() - 6; helpers.doKeys('2', 'd', '3', 'd'); eq(expectedLineCount, cm.lineCount()); @@ -1035,21 +1039,25 @@ testVim('yw_repeat', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq('word1\nword2', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); }, { value: ' word1\nword2' }); testVim('yy_multiply_repeat', function(cm, vim, helpers) { var curStart = makeCursor(0, 3); cm.setCursor(curStart); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); + var expectedBuffer = cm.getRange(new Pos(0, 0), + new Pos(6, 0)); var expectedLineCount = cm.lineCount(); helpers.doKeys('2', 'y', '3', 'y'); eq(expectedLineCount, cm.lineCount()); var register = helpers.getRegisterController().getRegister(); eq(expectedBuffer, register.toString()); is(register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); }); +testVim('2dd_blank_P', function(cm, vim, helpers) { + helpers.doKeys('2', 'd', 'd', 'P'); + eq('\na\n\n', cm.getValue()); +}, { value: '\na\n\n' }); // Change commands behave like d commands except that it also enters insert // mode. In addition, when the change is linewise, an additional newline is // inserted so that insert mode starts on that line. @@ -1069,13 +1077,13 @@ testVim('cw_repeat', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq('word1\nword2', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); eq('vim-insert', cm.getOption('keyMap')); }, { value: ' word1\nword2' }); testVim('cc_multiply_repeat', function(cm, vim, helpers) { cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); + var expectedBuffer = cm.getRange(new Pos(0, 0), + new Pos(6, 0)); var expectedLineCount = cm.lineCount() - 5; helpers.doKeys('2', 'c', '3', 'c'); eq(expectedLineCount, cm.lineCount()); @@ -1169,7 +1177,7 @@ testVim('g~w_repeat', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq('', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); }, { value: ' word1\nword2' }); testVim('g~g~', function(cm, vim, helpers) { var curStart = makeCursor(0, 3); @@ -1181,7 +1189,7 @@ testVim('g~g~', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq('', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); }, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); testVim('gu_and_gU', function(cm, vim, helpers) { var curStart = makeCursor(0, 7); @@ -1189,21 +1197,21 @@ testVim('gu_and_gU', function(cm, vim, helpers) { cm.setCursor(curStart); helpers.doKeys('2', 'g', 'U', 'w'); eq(cm.getValue(), 'wa wb xX WC wd'); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); helpers.doKeys('2', 'g', 'u', 'w'); eq(cm.getValue(), value); helpers.doKeys('2', 'g', 'U', 'B'); eq(cm.getValue(), 'wa WB Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); + eqCursorPos(makeCursor(0, 3), cm.getCursor()); cm.setCursor(makeCursor(0, 4)); helpers.doKeys('g', 'u', 'i', 'w'); eq(cm.getValue(), 'wa wb Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); + eqCursorPos(makeCursor(0, 3), cm.getCursor()); // TODO: support gUgU guu - // eqPos(makeCursor(0, 0), cm.getCursor()); + // eqCursorPos(makeCursor(0, 0), cm.getCursor()); var register = helpers.getRegisterController().getRegister(); eq('', register.toString()); @@ -1356,7 +1364,7 @@ testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz'); testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz'); testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz'); -testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0}); +testMotion('di(_outside_should_stay', ['d', 'i', '('], new Pos(0, 0), new Pos(0, 0)); // Open and close on different lines, equally indented testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); @@ -1428,7 +1436,7 @@ testVim('C', function(cm, vim, helpers) { var register = helpers.getRegisterController().getRegister(); eq('rd1', register.toString()); is(!register.linewise); - eqPos(curStart, cm.getCursor()); + eqCursorPos(curStart, cm.getCursor()); eq('vim-insert', cm.getOption('keyMap')); }, { value: ' word1\nword2\n word3' }); testVim('Y', function(cm, vim, helpers) { @@ -1437,8 +1445,8 @@ testVim('Y', function(cm, vim, helpers) { helpers.doKeys('Y'); eq(' word1\nword2\n word3', cm.getValue()); var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); + eq(' word1\n', register.toString()); + is(register.linewise); helpers.assertCursorAt(0, 3); }, { value: ' word1\nword2\n word3' }); testVim('~', function(cm, vim, helpers) { @@ -1477,6 +1485,19 @@ testVim('/ search forward', function(cm, vim, helpers) { helpers.assertCursorAt(0, 11); }); }, {value: '__jmp1 jmp2 jmp'}); +testVim('insert_ctrl_w', function(cm, vim, helpers) { + var curStart = makeCursor(0, 10); + cm.setCursor(curStart); + helpers.doKeys('a'); + helpers.doKeys(''); + eq('word1/', cm.getValue()); + var register = helpers.getRegisterController().getRegister(); + eq('word2', register.toString()); + is(!register.linewise); + var curEnd = makeCursor(0, 6); + eqCursorPos(curEnd, cm.getCursor()); + eq('vim-insert', cm.getOption('keyMap')); +}, { value: 'word1/word2' }); testVim('a', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('a'); @@ -1518,6 +1539,32 @@ testVim('i_repeat_delete', function(cm, vim, helpers) { eq('abe', cm.getValue()); helpers.assertCursorAt(0, 1); }, { value: 'abcde' }); +testVim('insert', function(cm, vim, helpers) { + helpers.doKeys('i'); + eq('vim-insert', cm.getOption('keyMap')); + eq(false, cm.state.overwrite); + helpers.doKeys(''); + eq('vim-replace', cm.getOption('keyMap')); + eq(true, cm.state.overwrite); + helpers.doKeys(''); + eq('vim-insert', cm.getOption('keyMap')); + eq(false, cm.state.overwrite); +}); +testVim('i_backspace', function(cm, vim, helpers) { + cm.setCursor(0, 10); + helpers.doKeys('i'); + helpers.doInsertModeKeys('Backspace'); + helpers.assertCursorAt(0, 9); + eq('012345678', cm.getValue()); +}, { value: '0123456789'}); +isAce || testVim('i_overwrite_backspace', function(cm, vim, helpers) { + cm.setCursor(0, 10); + helpers.doKeys('i'); + helpers.doKeys(''); + helpers.doInsertModeKeys('Backspace'); + helpers.assertCursorAt(Pos(0, 9, "after")); + eq('0123456789', cm.getValue()); +}, { value: '0123456789'}); testVim('A', function(cm, vim, helpers) { helpers.doKeys('A'); helpers.assertCursorAt(0, lines[0].length); @@ -1676,8 +1723,17 @@ testVim('r', function(cm, vim, helpers) { cm.setCursor(0, 4); helpers.doKeys('v', 'j', 'h', 'r', ''); eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); + if (isAce) return; + cm.setValue("ox"); + helpers.doKeys('r', ''); + eq('ox', cm.getValue()); + helpers.doKeys('r', ''); + eq('ox', cm.getValue()); + helpers.doKeys('r', ''); + eq('\nx', cm.getValue()); }, { value: 'wordet\nanother' }); testVim('r_visual_block', function(cm, vim, helpers) { + cm.setOption("tabSize", 4); cm.setCursor(2, 3); helpers.doKeys('', 'k', 'k', 'h', 'h', 'r', 'l'); eq('1lll\n5lll\nalllefg', cm.getValue()); @@ -1709,6 +1765,27 @@ testVim('mark', function(cm, vim, helpers) { helpers.doKeys('\'', 't'); helpers.assertCursorAt(2, 3); }); +isAce || testVim('mark\'', function(cm, vim, helpers) { + cm.setCursor(2, 2); + cm.setCursor(0, 0); + helpers.doKeys('`', '\''); + helpers.assertCursorAt(2, 2); + cm.setCursor(2, 0); + cm.replaceRange(' h', cm.getCursor()); + cm.setCursor(0, 0); + helpers.doKeys('\'', '\''); + helpers.assertCursorAt(2, 3); +}); +isAce || testVim('mark.', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doKeys('O', 'testing', ''); + cm.setCursor(3, 3); + helpers.doKeys('\'', '.'); + helpers.assertCursorAt(0, 0); + cm.setCursor(4, 4); + helpers.doKeys('`', '.'); + helpers.assertCursorAt(0, 6); +}); testVim('jumpToMark_next', function(cm, vim, helpers) { cm.setCursor(2, 2); helpers.doKeys('m', 't'); @@ -1948,7 +2025,7 @@ testVim('delmark_all', function(cm, vim, helpers) { testVim('visual', function(cm, vim, helpers) { helpers.doKeys('l', 'v', 'l', 'l'); helpers.assertCursorAt(0, 4); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); + eqCursorPos(makeCursor(0, 1), cm.getCursor('anchor')); helpers.doKeys('d'); eq('15', cm.getValue()); }, { value: '12345' }); @@ -1980,24 +2057,24 @@ testVim('visual_crossover_left', function(cm, vim, helpers) { testVim('visual_crossover_up', function(cm, vim, helpers) { cm.setCursor(3, 2); helpers.doKeys('v', 'j', 'k', 'k'); - eqPos(Pos(2, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); + eqCursorPos(Pos(2, 2), cm.getCursor('head')); + eqCursorPos(Pos(3, 3), cm.getCursor('anchor')); helpers.doKeys('k'); - eqPos(Pos(1, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); + eqCursorPos(Pos(1, 2), cm.getCursor('head')); + eqCursorPos(Pos(3, 3), cm.getCursor('anchor')); }, { value: 'cross\ncross\ncross\ncross\ncross\n'}); testVim('visual_crossover_down', function(cm, vim, helpers) { cm.setCursor(1, 2); helpers.doKeys('v', 'k', 'j', 'j'); - eqPos(Pos(2, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); + eqCursorPos(Pos(2, 3), cm.getCursor('head')); + eqCursorPos(Pos(1, 2), cm.getCursor('anchor')); helpers.doKeys('j'); - eqPos(Pos(3, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); + eqCursorPos(Pos(3, 3), cm.getCursor('head')); + eqCursorPos(Pos(1, 2), cm.getCursor('anchor')); }, { value: 'cross\ncross\ncross\ncross\ncross\n'}); testVim('visual_exit', function(cm, vim, helpers) { helpers.doKeys('', 'l', 'j', 'j', ''); - eqPos(cm.getCursor('anchor'), cm.getCursor('head')); + eqCursorPos(cm.getCursor('anchor'), cm.getCursor('head')); eq(vim.visualMode, false); }, { value: 'hello\nworld\nfoo' }); testVim('visual_line', function(cm, vim, helpers) { @@ -2080,7 +2157,7 @@ testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doKeys('', '3' , 'l', ''); - eqPos(makeCursor(0, 3), cm.getCursor()); + eqCursorPos(makeCursor(0, 3), cm.getCursor()); helpers.doKeys('h', '', '2' , 'j' ,'3' , 'l'); eq(cm.getSelections().join(), "3456,,cdef"); helpers.doKeys('4' , 'h'); @@ -2115,7 +2192,7 @@ testVim('visual_blank', function(cm, vim, helpers) { testVim('reselect_visual', function(cm, vim, helpers) { helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v'); helpers.assertCursorAt(0, 5); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); + eqCursorPos(makeCursor(0, 1), cm.getCursor('anchor')); helpers.doKeys('v'); cm.setCursor(1, 0); helpers.doKeys('v', 'l', 'l', 'p'); @@ -2124,15 +2201,15 @@ testVim('reselect_visual', function(cm, vim, helpers) { helpers.doKeys('g', 'v'); // here the fake cursor is at (1, 3) helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); + eqCursorPos(makeCursor(1, 0), cm.getCursor('anchor')); helpers.doKeys('v'); cm.setCursor(2, 0); helpers.doKeys('v', 'l', 'l', 'g', 'v'); helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); + eqCursorPos(makeCursor(1, 0), cm.getCursor('anchor')); helpers.doKeys('g', 'v'); helpers.assertCursorAt(2, 3); - eqPos(makeCursor(2, 0), cm.getCursor('anchor')); + eqCursorPos(makeCursor(2, 0), cm.getCursor('anchor')); eq('123456\n2345\nbar', cm.getValue()); }, { value: '123456\nfoo\nbar' }); testVim('reselect_visual_line', function(cm, vim, helpers) { @@ -2148,14 +2225,14 @@ testVim('reselect_visual_block', function(cm, vim, helpers) { helpers.doKeys('', 'k', 'h', ''); cm.setCursor(2, 1); helpers.doKeys('v', 'l', 'g', 'v'); - eqPos(Pos(1, 2), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); + eqCursorPos(Pos(1, 2), vim.sel.anchor); + eqCursorPos(Pos(0, 1), vim.sel.head); // Ensure selection is done with visual block mode rather than one // continuous range. eq(cm.getSelections().join(''), '23oo') helpers.doKeys('g', 'v'); - eqPos(Pos(2, 1), vim.sel.anchor); - eqPos(Pos(2, 2), vim.sel.head); + eqCursorPos(Pos(2, 1), vim.sel.anchor); + eqCursorPos(Pos(2, 2), vim.sel.head); helpers.doKeys(''); // Ensure selection of deleted range cm.setCursor(1, 1); @@ -2190,14 +2267,14 @@ testVim('o_visual', function(cm, vim, helpers) { testVim('o_visual_block', function(cm, vim, helpers) { cm.setCursor(0, 1); helpers.doKeys('','3','j','l','l', 'o'); - eqPos(Pos(3, 3), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); + eqCursorPos(Pos(3, 3), vim.sel.anchor); + eqCursorPos(Pos(0, 1), vim.sel.head); helpers.doKeys('O'); - eqPos(Pos(3, 1), vim.sel.anchor); - eqPos(Pos(0, 3), vim.sel.head); + eqCursorPos(Pos(3, 1), vim.sel.anchor); + eqCursorPos(Pos(0, 3), vim.sel.head); helpers.doKeys('o'); - eqPos(Pos(0, 3), vim.sel.anchor); - eqPos(Pos(3, 1), vim.sel.head); + eqCursorPos(Pos(0, 3), vim.sel.anchor); + eqCursorPos(Pos(3, 1), vim.sel.head); }, { value: 'abcd\nefgh\nijkl\nmnop'}); testVim('changeCase_visual', function(cm, vim, helpers) { cm.setCursor(0, 0); @@ -2637,6 +2714,14 @@ testVim('macro_search_2f', function(cm, vim, helpers) { helpers.doKeys('@', 'a'); helpers.assertCursorAt(0,9); }, { value: 'The quick brown fox jumped over the lazy dog.'}); +testVim('macro_yank_tick', function(cm, vim, helpers) { + cm.setCursor(0, 0); + // Start recording a macro into the \' register. + helpers.doKeys('q', '\''); + helpers.doKeys('y', '', '', '', '', 'p'); + helpers.assertCursorAt(0,4); + eq('the tex parrot', cm.getValue()); +}, { value: 'the ex parrot'}); testVim('yank_register', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doKeys('"', 'a', 'y', 'y'); @@ -3016,6 +3101,20 @@ testVim('._visual_>', function(cm, vim, helpers) { eq(' 1\n 2\n 3\n 4', cm.getValue()); helpers.assertCursorAt(2, 2); }, { value: '1\n2\n3\n4'}); +testVim('._replace_repeat', function(cm, vim, helpers) { + helpers.doKeys('R'); + cm.replaceRange('123', cm.getCursor(), offsetCursor(cm.getCursor(), 0, 3)); + cm.setCursor(0, 3); + helpers.doKeys(''); + helpers.doKeys('2', '.'); + eq('12123123\nabcdefg', cm.getValue()); + helpers.assertCursorAt(0, 7); + cm.setCursor(1, 0); + helpers.doKeys('.'); + eq('12123123\n123123g', cm.getValue()); + helpers.doKeys('l', '"', '.', 'p'); + eq('12123123\n123123g123', cm.getValue()); +}, { value: 'abcdef\nabcdefg'}); testVim('f;', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doKeys('f', 'x'); @@ -3205,11 +3304,12 @@ testVim('Ty,;', function(cm, vim, helpers) { eq('01230123456789', cm.getValue()); }, { value: '0123456789'}); testVim('HML', function(cm, vim, helpers) { + if (phantom) return; var lines = 35; var textHeight = cm.defaultTextHeight(); cm.setSize(600, lines*textHeight); cm.setCursor(120, 0); - cm.refresh(); //ace_patch + cm.ace.renderer.scrollCursorIntoView(); cm.refresh(); //ace_patch helpers.doKeys('H'); helpers.assertCursorAt(86, 2); helpers.doKeys('L'); @@ -3242,9 +3342,11 @@ forEach(['zb','zz','zt','z-','z.','z'], function(e, idx){ })()}); }); testVim('zb_to_bottom', function(cm, vim, helpers){ + if (isAce) return; var lineNum = 250; cm.setSize(600, 35*cm.defaultTextHeight()); cm.setCursor(lineNum, 0); + cm.ace.renderer.scrollCursorIntoView(); cm.refresh(); helpers.doKeys('z', 'b'); var scrollInfo = cm.getScrollInfo(); eq(scrollInfo.top + scrollInfo.clientHeight, cm.charCoords(Pos(lineNum, 0), 'local').bottom); @@ -3252,6 +3354,7 @@ testVim('zb_to_bottom', function(cm, vim, helpers){ return new Array(500).join('\n'); })()}); testVim('zt_to_top', function(cm, vim, helpers){ + if (isAce) return; var lineNum = 250; cm.setSize(600, 35*cm.defaultTextHeight()); cm.setCursor(lineNum, 0); @@ -3261,9 +3364,11 @@ testVim('zt_to_top', function(cm, vim, helpers){ return new Array(500).join('\n'); })()}); testVim('zb'); + eq(expectedValue, cm.getValue()); + helpers.assertCursorAt(0, 5); +}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); +testVim('i_indent_left', function(cm, vim, helpers) { + cm.setCursor(0, 3); + var expectedValue = ' word1\nword2\nword3 '; + helpers.doKeys('i', ''); + eq(expectedValue, cm.getValue()); + helpers.assertCursorAt(0, 1); +}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); + // Ex mode tests testVim('ex_go_to_line', function(cm, vim, helpers) { cm.setCursor(0, 0); helpers.doEx('4'); helpers.assertCursorAt(3, 0); }, { value: 'a\nb\nc\nd\ne\n'}); +testVim('ex_go_to_mark', function(cm, vim, helpers) { + cm.setCursor(3, 0); + helpers.doKeys('m', 'a'); + cm.setCursor(0, 0); + helpers.doEx('\'a'); + helpers.assertCursorAt(3, 0); +}, { value: 'a\nb\nc\nd\ne\n'}); +testVim('ex_go_to_line_offset', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doEx('+3'); + helpers.assertCursorAt(3, 0); + helpers.doEx('-1'); + helpers.assertCursorAt(2, 0); + helpers.doEx('.2'); + helpers.assertCursorAt(4, 0); + helpers.doEx('.-3'); + helpers.assertCursorAt(1, 0); +}, { value: 'a\nb\nc\nd\ne\n'}); +testVim('ex_go_to_mark_offset', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('m', 'a'); + cm.setCursor(0, 0); + helpers.doEx('\'a1'); + helpers.assertCursorAt(3, 0); + helpers.doEx('\'a-1'); + helpers.assertCursorAt(1, 0); + helpers.doEx('\'a+2'); + helpers.assertCursorAt(4, 0); +}, { value: 'a\nb\nc\nd\ne\n'}); testVim('ex_write', function(cm, vim, helpers) { var tmp = CodeMirror.commands.save; var written; @@ -3534,24 +3684,44 @@ testVim('ex_sort_hex', function(cm, vim, helpers) { }, { value: '6\nd3\n s5\n&0xB\n.9'}); testVim('ex_sort_octal', function(cm, vim, helpers) { helpers.doEx('sort o'); - eq('.8\n.9\nd3\n s5\n6', cm.getValue()); + eq('.9\n.8\nd3\n s5\n6', cm.getValue()); }, { value: '6\nd3\n s5\n.9\n.8'}); testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { helpers.doEx('sort d'); - eq('y\nz\nc1\nb2\na3', cm.getValue()); + eq('z\ny\nc1\nb2\na3', cm.getValue()); }, { value: 'a3\nz\nc1\ny\nb2'}); testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { helpers.doEx('sort! d'); eq('a3\nb2\nc1\nz\ny', cm.getValue()); }, { value: 'a3\nz\nc1\ny\nb2'}); -testVim('ex_sort_patterns_not_supported', function(cm, vim, helpers) { - var notified = false; - cm.openNotification = helpers.fakeOpenNotification(function(text) { - notified = /patterns not supported/.test(text); - }); - helpers.doEx('sort /abc/'); - is(notified, 'No notification.'); -}); +testVim('ex_sort_pattern_alpha', function(cm, vim, helpers) { + helpers.doEx('sort /[a-z]/'); + eq('a3\nb2\nc1\ny\nz', cm.getValue()); +}, { value: 'z\ny\nc1\nb2\na3'}); +testVim('ex_sort_pattern_alpha_reverse', function(cm, vim, helpers) { + helpers.doEx('sort! /[a-z]/'); + eq('z\ny\nc1\nb2\na3', cm.getValue()); +}, { value: 'z\ny\nc1\nb2\na3'}); +testVim('ex_sort_pattern_alpha_ignoreCase', function(cm, vim, helpers) { + helpers.doEx('sort i/[a-z]/'); + eq('a3\nb2\nC1\nY\nz', cm.getValue()); +}, { value: 'z\nY\nC1\nb2\na3'}); +testVim('ex_sort_pattern_alpha_longer', function(cm, vim, helpers) { + helpers.doEx('sort /[a-z]+/'); + eq('a\naa\nab\nade\nadele\nadelle\nadriana\nalex\nalexandra\nb\nc\ny\nz', cm.getValue()); +}, { value: 'z\nab\naa\nade\nadelle\nalexandra\nalex\nadriana\nadele\ny\nc\nb\na'}); +testVim('ex_sort_pattern_alpha_only', function(cm, vim, helpers) { + helpers.doEx('sort /^[a-z]$/'); + eq('z1\ny2\na3\nb\nc', cm.getValue()); +}, { value: 'z1\ny2\na3\nc\nb'}); +testVim('ex_sort_pattern_alpha_only_reverse', function(cm, vim, helpers) { + helpers.doEx('sort! /^[a-z]$/'); + eq('c\nb\nz1\ny2\na3', cm.getValue()); +}, { value: 'z1\ny2\na3\nc\nb'}); +testVim('ex_sort_pattern_alpha_num', function(cm, vim, helpers) { + helpers.doEx('sort /[a-z][0-9]/'); + eq('c\nb\na3\ny2\nz1', cm.getValue()); +}, { value: 'z1\ny2\na3\nc\nb'}); // test for :global command testVim('ex_global', function(cm, vim, helpers) { cm.setCursor(0, 0); @@ -3593,6 +3763,11 @@ testVim('ex_substitute_same_line', function(cm, vim, helpers) { helpers.doEx('s/one/two/g'); eq('one one\n two two', cm.getValue()); }, { value: 'one one\n one one'}); +testVim('ex_substitute_alternate_separator', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doEx('s#o/e#two#g'); + eq('o/e o/e\n two two', cm.getValue()); +}, { value: 'o/e o/e\n o/e o/e'}); testVim('ex_substitute_full_file', function(cm, vim, helpers) { cm.setCursor(1, 0); helpers.doEx('%s/one/two/g'); @@ -3603,6 +3778,50 @@ testVim('ex_substitute_input_range', function(cm, vim, helpers) { helpers.doEx('1,3s/\\d/0/g'); eq('0\n0\n0\n4', cm.getValue()); }, { value: '1\n2\n3\n4' }); +testVim('ex_substitute_range_current_to_input', function(cm, vim, helpers) { + cm.setCursor(1, 0); + helpers.doEx('.,3s/\\d/0/g'); + eq('1\n0\n0\n4', cm.getValue()); +}, { value: '1\n2\n3\n4' }); +testVim('ex_substitute_range_input_to_current', function(cm, vim, helpers) { + cm.setCursor(3, 0); + helpers.doEx('2,.s/\\d/0/g'); + eq('1\n0\n0\n0\n5', cm.getValue()); +}, { value: '1\n2\n3\n4\n5' }); +testVim('ex_substitute_range_offset', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doEx('-1,+1s/\\d/0/g'); + eq('1\n0\n0\n0\n5', cm.getValue()); +}, { value: '1\n2\n3\n4\n5' }); +testVim('ex_substitute_range_implicit_offset', function(cm, vim, helpers) { + cm.setCursor(0, 0); + helpers.doEx('.1,.3s/\\d/0/g'); + eq('1\n0\n0\n0\n5', cm.getValue()); +}, { value: '1\n2\n3\n4\n5' }); +testVim('ex_substitute_to_eof', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doEx('.,$s/\\d/0/g'); + eq('1\n2\n0\n0\n0', cm.getValue()); +}, { value: '1\n2\n3\n4\n5' }); +testVim('ex_substitute_to_relative_eof', function(cm, vim, helpers) { + cm.setCursor(4, 0); + helpers.doEx('2,$-2s/\\d/0/g'); + eq('1\n0\n0\n4\n5', cm.getValue()); +}, { value: '1\n2\n3\n4\n5' }); +testVim('ex_substitute_range_mark', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('ma'); + cm.setCursor(0, 0); + helpers.doEx('.,\'as/\\d/0/g'); + eq('0\n0\n0\n4\n5', cm.getValue()); +}, { value: '1\n2\n3\n4\n5' }); +testVim('ex_substitute_range_mark_offset', function(cm, vim, helpers) { + cm.setCursor(2, 0); + helpers.doKeys('ma'); + cm.setCursor(0, 0); + helpers.doEx('\'a-1,\'a+1s/\\d/0/g'); + eq('1\n0\n0\n0\n5', cm.getValue()); +}, { value: '1\n2\n3\n4\n5' }); testVim('ex_substitute_visual_range', function(cm, vim, helpers) { cm.setCursor(1, 0); // Set last visual mode selection marks '< and '> at lines 2 and 4 @@ -3713,6 +3932,14 @@ testSubstitute('ex_substitute_multibackslash_replacement', { value: 'one,two \n three,four', expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. +isAce || testSubstitute('ex_substitute_dollar_match', { + value: 'one,two \n three,four', + expectedValue: 'one,two ,\n three,four', + expr: '%s/$/,/g'}); +isAce || testSubstitute('ex_substitute_newline_match', { + value: 'one,two \n three,four', + expectedValue: 'one,two , three,four', + expr: '%s/\\n/,/g'}); testSubstitute('ex_substitute_newline_replacement', { value: 'one,two \n three,four', expectedValue: 'one\ntwo \n three\nfour', @@ -3792,7 +4019,7 @@ function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, } catch(e) { throw e } finally { - // Restore overriden functions. + // Restore overridden functions. CodeMirror.keyName = savedKeyName; cm.openDialog = savedOpenDialog; } @@ -3835,6 +4062,14 @@ testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { helpers.doKeys('n'); helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); }, { value: 'match nope match \n nope Match' }); +testVim('ex_yank', function (cm, vim, helpers) { + var curStart = makeCursor(3, 0); + cm.setCursor(curStart); + helpers.doEx('y'); + var register = helpers.getRegisterController().getRegister(); + var line = cm.getLine(3); + eq(line + '\n', register.toString()); +}); testVim('set_boolean', function(cm, vim, helpers) { CodeMirror.Vim.defineOption('testoption', true, 'boolean'); // Test default value is set. @@ -3842,7 +4077,7 @@ testVim('set_boolean', function(cm, vim, helpers) { expectFail(function() { // Test fail to set to non-boolean CodeMirror.Vim.setOption('testoption', '5'); - }); + }, isAce); // Test setOption CodeMirror.Vim.setOption('testoption', false); is(!CodeMirror.Vim.getOption('testoption')); @@ -3854,7 +4089,7 @@ testVim('ex_set_boolean', function(cm, vim, helpers) { expectFail(function() { // Test fail to set to non-boolean helpers.doEx('set testoption=22'); - }); + }, isAce); // Test setOption helpers.doEx('set notestoption'); is(!CodeMirror.Vim.getOption('testoption')); @@ -3863,11 +4098,11 @@ testVim('set_string', function(cm, vim, helpers) { CodeMirror.Vim.defineOption('testoption', 'a', 'string'); // Test default value is set. eq('a', CodeMirror.Vim.getOption('testoption')); - expectFail(function() { + isAce || expectFail(function() { // Test fail to set non-string. CodeMirror.Vim.setOption('testoption', true); }); - expectFail(function() { + isAce || expectFail(function() { // Test fail to set 'notestoption' CodeMirror.Vim.setOption('notestoption', 'b'); }); @@ -3879,7 +4114,7 @@ testVim('ex_set_string', function(cm, vim, helpers) { CodeMirror.Vim.defineOption('testopt', 'a', 'string'); // Test default value is set. eq('a', CodeMirror.Vim.getOption('testopt')); - expectFail(function() { + isAce || expectFail(function() { // Test fail to set 'notestopt' helpers.doEx('set notestopt=b'); }); @@ -3931,7 +4166,7 @@ testVim('ex_set_callback', function(cm, vim, helpers) { expectFail(function() { // Test fail to set 'notestopt' helpers.doEx('set notestopt=b'); - }); + }, isAce); // Test setOption (Identical to the string tests, but via callback instead) helpers.doEx('set testopt=c') eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global @@ -3993,6 +4228,7 @@ testVim('ex_unmap_key2key', function(cm, vim, helpers) { eq('vim-insert', cm.getOption('keyMap')); }, { value: 'abc' }); testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { + if (isAce) return; expectFail(function() { helpers.doEx('unmap a'); }); @@ -4110,10 +4346,256 @@ testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { // Test event handlers testVim('beforeSelectionChange', function(cm, vim, helpers) { cm.setCursor(0, 100); - eqPos(cm.getCursor('head'), cm.getCursor('anchor')); + eqCursorPos(cm.getCursor('head'), cm.getCursor('anchor')); }, { value: 'abc' }); +testVim('increment_binary', function(cm, vim, helpers) { + cm.setCursor(0, 4); + helpers.doKeys(''); + eq('0b001', cm.getValue()); + helpers.doKeys(''); + eq('0b010', cm.getValue()); + helpers.doKeys(''); + eq('0b001', cm.getValue()); + helpers.doKeys(''); + eq('0b000', cm.getValue()); + cm.setCursor(0, 0); + helpers.doKeys(''); + eq('0b001', cm.getValue()); + helpers.doKeys(''); + eq('0b010', cm.getValue()); + helpers.doKeys(''); + eq('0b001', cm.getValue()); + helpers.doKeys(''); + eq('0b000', cm.getValue()); +}, { value: '0b000' }); +testVim('increment_octal', function(cm, vim, helpers) { + cm.setCursor(0, 2); + helpers.doKeys(''); + eq('001', cm.getValue()); + helpers.doKeys(''); + eq('002', cm.getValue()); + helpers.doKeys(''); + eq('003', cm.getValue()); + helpers.doKeys(''); + eq('004', cm.getValue()); + helpers.doKeys(''); + eq('005', cm.getValue()); + helpers.doKeys(''); + eq('006', cm.getValue()); + helpers.doKeys(''); + eq('007', cm.getValue()); + helpers.doKeys(''); + eq('010', cm.getValue()); + helpers.doKeys(''); + eq('007', cm.getValue()); + helpers.doKeys(''); + eq('006', cm.getValue()); + helpers.doKeys(''); + eq('005', cm.getValue()); + helpers.doKeys(''); + eq('004', cm.getValue()); + helpers.doKeys(''); + eq('003', cm.getValue()); + helpers.doKeys(''); + eq('002', cm.getValue()); + helpers.doKeys(''); + eq('001', cm.getValue()); + helpers.doKeys(''); + eq('000', cm.getValue()); + cm.setCursor(0, 0); + helpers.doKeys(''); + eq('001', cm.getValue()); + helpers.doKeys(''); + eq('002', cm.getValue()); + helpers.doKeys(''); + eq('001', cm.getValue()); + helpers.doKeys(''); + eq('000', cm.getValue()); +}, { value: '000' }); + +testVim('increment_decimal', function(cm, vim, helpers) { + cm.setCursor(0, 2); + helpers.doKeys(''); + eq('101', cm.getValue()); + helpers.doKeys(''); + eq('102', cm.getValue()); + helpers.doKeys(''); + eq('103', cm.getValue()); + helpers.doKeys(''); + eq('104', cm.getValue()); + helpers.doKeys(''); + eq('105', cm.getValue()); + helpers.doKeys(''); + eq('106', cm.getValue()); + helpers.doKeys(''); + eq('107', cm.getValue()); + helpers.doKeys(''); + eq('108', cm.getValue()); + helpers.doKeys(''); + eq('109', cm.getValue()); + helpers.doKeys(''); + eq('110', cm.getValue()); + helpers.doKeys(''); + eq('109', cm.getValue()); + helpers.doKeys(''); + eq('108', cm.getValue()); + helpers.doKeys(''); + eq('107', cm.getValue()); + helpers.doKeys(''); + eq('106', cm.getValue()); + helpers.doKeys(''); + eq('105', cm.getValue()); + helpers.doKeys(''); + eq('104', cm.getValue()); + helpers.doKeys(''); + eq('103', cm.getValue()); + helpers.doKeys(''); + eq('102', cm.getValue()); + helpers.doKeys(''); + eq('101', cm.getValue()); + helpers.doKeys(''); + eq('100', cm.getValue()); + cm.setCursor(0, 0); + helpers.doKeys(''); + eq('101', cm.getValue()); + helpers.doKeys(''); + eq('102', cm.getValue()); + helpers.doKeys(''); + eq('101', cm.getValue()); + helpers.doKeys(''); + eq('100', cm.getValue()); +}, { value: '100' }); + +testVim('increment_decimal_single_zero', function(cm, vim, helpers) { + helpers.doKeys(''); + eq('1', cm.getValue()); + helpers.doKeys(''); + eq('2', cm.getValue()); + helpers.doKeys(''); + eq('3', cm.getValue()); + helpers.doKeys(''); + eq('4', cm.getValue()); + helpers.doKeys(''); + eq('5', cm.getValue()); + helpers.doKeys(''); + eq('6', cm.getValue()); + helpers.doKeys(''); + eq('7', cm.getValue()); + helpers.doKeys(''); + eq('8', cm.getValue()); + helpers.doKeys(''); + eq('9', cm.getValue()); + helpers.doKeys(''); + eq('10', cm.getValue()); + helpers.doKeys(''); + eq('9', cm.getValue()); + helpers.doKeys(''); + eq('8', cm.getValue()); + helpers.doKeys(''); + eq('7', cm.getValue()); + helpers.doKeys(''); + eq('6', cm.getValue()); + helpers.doKeys(''); + eq('5', cm.getValue()); + helpers.doKeys(''); + eq('4', cm.getValue()); + helpers.doKeys(''); + eq('3', cm.getValue()); + helpers.doKeys(''); + eq('2', cm.getValue()); + helpers.doKeys(''); + eq('1', cm.getValue()); + helpers.doKeys(''); + eq('0', cm.getValue()); + cm.setCursor(0, 0); + helpers.doKeys(''); + eq('1', cm.getValue()); + helpers.doKeys(''); + eq('2', cm.getValue()); + helpers.doKeys(''); + eq('1', cm.getValue()); + helpers.doKeys(''); + eq('0', cm.getValue()); +}, { value: '0' }); + +testVim('increment_hexadecimal', function(cm, vim, helpers) { + cm.setCursor(0, 2); + helpers.doKeys(''); + eq('0x1', cm.getValue()); + helpers.doKeys(''); + eq('0x2', cm.getValue()); + helpers.doKeys(''); + eq('0x3', cm.getValue()); + helpers.doKeys(''); + eq('0x4', cm.getValue()); + helpers.doKeys(''); + eq('0x5', cm.getValue()); + helpers.doKeys(''); + eq('0x6', cm.getValue()); + helpers.doKeys(''); + eq('0x7', cm.getValue()); + helpers.doKeys(''); + eq('0x8', cm.getValue()); + helpers.doKeys(''); + eq('0x9', cm.getValue()); + helpers.doKeys(''); + eq('0xa', cm.getValue()); + helpers.doKeys(''); + eq('0xb', cm.getValue()); + helpers.doKeys(''); + eq('0xc', cm.getValue()); + helpers.doKeys(''); + eq('0xd', cm.getValue()); + helpers.doKeys(''); + eq('0xe', cm.getValue()); + helpers.doKeys(''); + eq('0xf', cm.getValue()); + helpers.doKeys(''); + eq('0x10', cm.getValue()); + helpers.doKeys(''); + eq('0x0f', cm.getValue()); + helpers.doKeys(''); + eq('0x0e', cm.getValue()); + helpers.doKeys(''); + eq('0x0d', cm.getValue()); + helpers.doKeys(''); + eq('0x0c', cm.getValue()); + helpers.doKeys(''); + eq('0x0b', cm.getValue()); + helpers.doKeys(''); + eq('0x0a', cm.getValue()); + helpers.doKeys(''); + eq('0x09', cm.getValue()); + helpers.doKeys(''); + eq('0x08', cm.getValue()); + helpers.doKeys(''); + eq('0x07', cm.getValue()); + helpers.doKeys(''); + eq('0x06', cm.getValue()); + helpers.doKeys(''); + eq('0x05', cm.getValue()); + helpers.doKeys(''); + eq('0x04', cm.getValue()); + helpers.doKeys(''); + eq('0x03', cm.getValue()); + helpers.doKeys(''); + eq('0x02', cm.getValue()); + helpers.doKeys(''); + eq('0x01', cm.getValue()); + helpers.doKeys(''); + eq('0x00', cm.getValue()); + cm.setCursor(0, 0); + helpers.doKeys(''); + eq('0x01', cm.getValue()); + helpers.doKeys(''); + eq('0x02', cm.getValue()); + helpers.doKeys(''); + eq('0x01', cm.getValue()); + helpers.doKeys(''); + eq('0x00', cm.getValue()); +}, { value: '0x0' }); }); diff --git a/plugins/node_modules/ace/lib/ace/layer/font_metrics.js b/plugins/node_modules/ace/lib/ace/layer/font_metrics.js index badebe92..5f2a81fd 100644 --- a/plugins/node_modules/ace/lib/ace/layer/font_metrics.js +++ b/plugins/node_modules/ace/lib/ace/layer/font_metrics.js @@ -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); }); diff --git a/plugins/node_modules/ace/lib/ace/layer/text.js b/plugins/node_modules/ace/lib/ace/layer/text.js index 8f989726..675a58ef 100644 --- a/plugins/node_modules/ace/lib/ace/layer/text.js +++ b/plugins/node_modules/ace/lib/ace/layer/text.js @@ -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'; diff --git a/plugins/node_modules/ace/lib/ace/lib/dom.js b/plugins/node_modules/ace/lib/ace/lib/dom.js index 69c4cb94..ae3513ce 100644 --- a/plugins/node_modules/ace/lib/ace/lib/dom.js +++ b/plugins/node_modules/ace/lib/ace/lib/dom.js @@ -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, "") || {}; }; }); diff --git a/plugins/node_modules/ace/lib/ace/mode/_test/highlight_rules_test.js b/plugins/node_modules/ace/lib/ace/mode/_test/highlight_rules_test.js index d9d4a359..8446304e 100644 --- a/plugins/node_modules/ace/lib/ace/mode/_test/highlight_rules_test.js +++ b/plugins/node_modules/ace/lib/ace/mode/_test/highlight_rules_test.js @@ -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); diff --git a/plugins/node_modules/ace/lib/ace/mode/_test/text_markdown.txt b/plugins/node_modules/ace/lib/ace/mode/_test/text_markdown.txt index 0450c820..55776736 100644 --- a/plugins/node_modules/ace/lib/ace/mode/_test/text_markdown.txt +++ b/plugins/node_modules/ace/lib/ace/mode/_test/text_markdown.txt @@ -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/) # diff --git a/plugins/node_modules/ace/lib/ace/mode/_test/tokens_markdown.json b/plugins/node_modules/ace/lib/ace/mode/_test/tokens_markdown.json index 3ac5c131..9ed34bc0 100644 --- a/plugins/node_modules/ace/lib/ace/mode/_test/tokens_markdown.json +++ b/plugins/node_modules/ace/lib/ace/mode/_test/tokens_markdown.json @@ -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" -]] +]] \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/mode/_test/tokens_praat.json b/plugins/node_modules/ace/lib/ace/mode/_test/tokens_praat.json index 2dff34bf..763c038b 100644 --- a/plugins/node_modules/ace/lib/ace/mode/_test/tokens_praat.json +++ b/plugins/node_modules/ace/lib/ace/mode/_test/tokens_praat.json @@ -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"," "] diff --git a/plugins/node_modules/ace/lib/ace/mode/_test/tokens_verilog.json b/plugins/node_modules/ace/lib/ace/mode/_test/tokens_verilog.json index 9680a964..75ba9c79 100644 --- a/plugins/node_modules/ace/lib/ace/mode/_test/tokens_verilog.json +++ b/plugins/node_modules/ace/lib/ace/mode/_test/tokens_verilog.json @@ -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"] ]] \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/mode/assembly_x86.js b/plugins/node_modules/ace/lib/ace/mode/assembly_x86.js index 21858f42..525f1778 100644 --- a/plugins/node_modules/ace/lib/ace/mode/assembly_x86.js +++ b/plugins/node_modules/ace/lib/ace/mode/assembly_x86.js @@ -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; -}); \ No newline at end of file +}); diff --git a/plugins/node_modules/ace/lib/ace/mode/behaviour/behaviour_test.js b/plugins/node_modules/ace/lib/ace/mode/behaviour/behaviour_test.js index 118ae021..500f3971 100644 --- a/plugins/node_modules/ace/lib/ace/mode/behaviour/behaviour_test.js +++ b/plugins/node_modules/ace/lib/ace/mode/behaviour/behaviour_test.js @@ -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(["", " " ].join("\n")); @@ -198,6 +202,89 @@ module.exports = { " > ", "'> >" ].join("\n")); + + editor.setValue(""); + "
".split("").forEach(function(ch) { + exec("insertstring", 1, ch); + }); + assert.equal(editor.getValue(), "
"); + exec("insertstring", 1, ">"); + assert.equal(editor.getValue(), "
>
"); + + editor.setValue("
", 1); + exec("gotoleft", 7); + exec("insertstring", 1, '"'); + assert.equal(editor.getValue(), "
"); + exec("insertstring", 1, '"'); + exec("gotoright", 1); + exec("insertstring", 1, "\n"); + assert.equal(editor.getValue(), "
\n \n
"); + + exec("undo", 1); + assert.equal(editor.getValue(), "
"); + exec("gotoleft", 1); + exec("backspace", 1); + assert.equal(editor.getValue(), "
"); + exec("undo", 1); + exec("gotoleft", 1); + exec("backspace", 1); + assert.equal(editor.getValue(), "
"); + exec("backspace", 1); + assert.equal(editor.getValue(), "
"); + + editor.setValue("
", 1); + editor.selection.moveTo(0, 9); + exec("insertstring", 1, "\n"); + assert.equal(editor.getValue(), "
\n
"); + + editor.setValue("
", 1); + exec("insertstring", 1, "\n"); + assert.equal(editor.getValue(), "
\n "); + + editor.setValue("

", 1); + editor.selection.moveTo(0, 8); + exec("insertstring", 1, "\n"); + assert.equal(editor.getValue(), "
\n
"); + + editor.setValue("
x"); + + editor.setValue(""); + "
".split("").forEach(function(ch) { + exec("insertstring", 1, ch); + }); + assert.equal(editor.getValue(), "
"); }, "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;}"); } + }; }); diff --git a/plugins/node_modules/ace/lib/ace/mode/behaviour/css.js b/plugins/node_modules/ace/lib/ace/mode/behaviour/css.js index f947f120..abde6ead 100644 --- a/plugins/node_modules/ace/lib/ace/mode/behaviour/css.js +++ b/plugins/node_modules/ace/lib/ace/mode/behaviour/css.js @@ -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); diff --git a/plugins/node_modules/ace/lib/ace/mode/behaviour/xml.js b/plugins/node_modules/ace/lib/ace/mode/behaviour/xml.js index 634d9b0d..ae92e91b 100644 --- a/plugins/node_modules/ace/lib/ace/mode/behaviour/xml.js +++ b/plugins/node_modules/ace/lib/ace/mode/behaviour/xml.js @@ -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(); } diff --git a/plugins/node_modules/ace/lib/ace/mode/c_cpp_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/c_cpp_highlight_rules.js index 20bbe5a0..82c0a3c3 100644 --- a/plugins/node_modules/ace/lib/ace/mode/c_cpp_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/c_cpp_highlight_rules.js @@ -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" ); diff --git a/plugins/node_modules/ace/lib/ace/mode/css.js b/plugins/node_modules/ace/lib/ace/mode/css.js index f905fe65..cafa502c 100644 --- a/plugins/node_modules/ace/lib/ace/mode/css.js +++ b/plugins/node_modules/ace/lib/ace/mode/css.js @@ -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); diff --git a/plugins/node_modules/ace/lib/ace/mode/css/csslint.js b/plugins/node_modules/ace/lib/ace/mode/css/csslint.js index 5c888436..fec65280 100644 --- a/plugins/node_modules/ace/lib/ace/mode/css/csslint.js +++ b/plugins/node_modules/ace/lib/ace/mode/css/csslint.js @@ -3929,8 +3929,10 @@ var Properties = { "marquee-style" : 1, "max-height" : " | | | none | inherit", "max-width" : " | | | none | inherit", + "max-zoom" : " | | auto", "min-height" : " | | | contain-floats | -moz-contain-floats | -webkit-contain-floats | inherit", "min-width" : " | | | contain-floats | -moz-contain-floats | -webkit-contain-floats | inherit", + "min-zoom" : " | | 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 | | ", diff --git a/plugins/node_modules/ace/lib/ace/mode/css_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/css_highlight_rules.js index 153ea5a0..4276ec21 100644 --- a/plugins/node_modules/ace/lib/ace/mode/css_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/css_highlight_rules.js @@ -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 diff --git a/plugins/node_modules/ace/lib/ace/mode/html_completions.js b/plugins/node_modules/ace/lib/ace/mode/html_completions.js index 679e4f82..0919bf0f 100644 --- a/plugins/node_modules/ace/lib/ace/mode/html_completions.js +++ b/plugins/node_modules/ace/lib/ace/mode/html_completions.js @@ -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); diff --git a/plugins/node_modules/ace/lib/ace/mode/kotlin.js b/plugins/node_modules/ace/lib/ace/mode/kotlin.js index 9a0a5673..3f9b0f63 100644 --- a/plugins/node_modules/ace/lib/ace/mode/kotlin.js +++ b/plugins/node_modules/ace/lib/ace/mode/kotlin.js @@ -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); diff --git a/plugins/node_modules/ace/lib/ace/mode/less.js b/plugins/node_modules/ace/lib/ace/mode/less.js index 0607614d..752558bd 100644 --- a/plugins/node_modules/ace/lib/ace/mode/less.js +++ b/plugins/node_modules/ace/lib/ace/mode/less.js @@ -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); diff --git a/plugins/node_modules/ace/lib/ace/mode/livescript.js b/plugins/node_modules/ace/lib/ace/mode/livescript.js index 9d4ff4fe..e66c6942 100644 --- a/plugins/node_modules/ace/lib/ace/mode/livescript.js +++ b/plugins/node_modules/ace/lib/ace/mode/livescript.js @@ -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){ diff --git a/plugins/node_modules/ace/lib/ace/mode/lua/luaparse.js b/plugins/node_modules/ace/lib/ace/mode/lua/luaparse.js index 9be01838..3339f6e5 100644 --- a/plugins/node_modules/ace/lib/ace/mode/lua/luaparse.js +++ b/plugins/node_modules/ace/lib/ace/mode/lua/luaparse.js @@ -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) { diff --git a/plugins/node_modules/ace/lib/ace/mode/markdown_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/markdown_highlight_rules.js index 254b9cfb..bacf594a 100644 --- a/plugins/node_modules/ace/lib/ace/mode/markdown_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/markdown_highlight_rules.js @@ -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-"), diff --git a/plugins/node_modules/ace/lib/ace/mode/nsis_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/nsis_highlight_rules.js index 33dd5293..3f270785 100644 --- a/plugins/node_modules/ace/lib/ace/mode/nsis_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/nsis_highlight_rules.js @@ -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/ diff --git a/plugins/node_modules/ace/lib/ace/mode/php_completions.js b/plugins/node_modules/ace/lib/ace/mode/php_completions.js index 62bebb9f..b6719795 100644 --- a/plugins/node_modules/ace/lib/ace/mode/php_completions.js +++ b/plugins/node_modules/ace/lib/ace/mode/php_completions.js @@ -9330,10 +9330,20 @@ var PhpCompletions = function() { if (!token) return []; + + if (token.type==='support.php_tag' && token.value===' 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); diff --git a/plugins/node_modules/ace/lib/ace/mode/php_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/php_highlight_rules.js index 8420d150..7bb3e4c2 100644 --- a/plugins/node_modules/ace/lib/ace/mode/php_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/php_highlight_rules.js @@ -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 : "[[({]" diff --git a/plugins/node_modules/ace/lib/ace/mode/praat_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/praat_highlight_rules.js index 29f19323..e2e6b055 100644 --- a/plugins/node_modules/ace/lib/ace/mode/praat_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/praat_highlight_rules.js @@ -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"], diff --git a/plugins/node_modules/ace/lib/ace/mode/python_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/python_highlight_rules.js index 34607551..18f2370a 100644 --- a/plugins/node_modules/ace/lib/ace/mode/python_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/python_highlight_rules.js @@ -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"); diff --git a/plugins/node_modules/ace/lib/ace/mode/red.js b/plugins/node_modules/ace/lib/ace/mode/red.js index c7ca8dbc..573136c3 100644 --- a/plugins/node_modules/ace/lib/ace/mode/red.js +++ b/plugins/node_modules/ace/lib/ace/mode/red.js @@ -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); diff --git a/plugins/node_modules/ace/lib/ace/mode/red_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/red_highlight_rules.js index e7315fe2..c67ae8bd 100644 --- a/plugins/node_modules/ace/lib/ace/mode/red_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/red_highlight_rules.js @@ -63,7 +63,7 @@ var RedHighlightRules = function() { {token : "string.tag", 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; +}); diff --git a/plugins/node_modules/ace/lib/ace/mode/verilog.js b/plugins/node_modules/ace/lib/ace/mode/verilog.js index 5c2ca733..707773cc 100644 --- a/plugins/node_modules/ace/lib/ace/mode/verilog.js +++ b/plugins/node_modules/ace/lib/ace/mode/verilog.js @@ -46,6 +46,8 @@ oop.inherits(Mode, TextMode); this.lineCommentStart = "//"; this.blockComment = {start: "/*", end: "*/"}; + this.$quotes = { '"': '"' }; + this.$id = "ace/mode/verilog"; }).call(Mode.prototype); diff --git a/plugins/node_modules/ace/lib/ace/mode/verilog_highlight_rules.js b/plugins/node_modules/ace/lib/ace/mode/verilog_highlight_rules.js index 024b73fa..f820fbcf 100644 --- a/plugins/node_modules/ace/lib/ace/mode/verilog_highlight_rules.js +++ b/plugins/node_modules/ace/lib/ace/mode/verilog_highlight_rules.js @@ -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" diff --git a/plugins/node_modules/ace/lib/ace/mode/xml/dom.js b/plugins/node_modules/ace/lib/ace/mode/xml/dom.js index 019811bd..4d5ff17a 100644 --- a/plugins/node_modules/ace/lib/ace/mode/xml/dom.js +++ b/plugins/node_modules/ace/lib/ace/mode/xml/dom.js @@ -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' && '>' || c == '&' && '&' || c == '"' && '"' || - '&#'+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 DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout) + if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimeout) this.startSelect(this.mousedownEvent.getDocumentPosition()); }; diff --git a/plugins/node_modules/ace/lib/ace/mouse/mouse_handler.js b/plugins/node_modules/ace/lib/ace/mouse/mouse_handler.js index bca2ea93..a383ba32 100644 --- a/plugins/node_modules/ace/lib/ace/mouse/mouse_handler.js +++ b/plugins/node_modules/ace/lib/ace/mouse/mouse_handler.js @@ -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} }); diff --git a/plugins/node_modules/ace/lib/ace/selection.js b/plugins/node_modules/ace/lib/ace/selection.js index a5824f10..a9dd9251 100644 --- a/plugins/node_modules/ace/lib/ace/selection.js +++ b/plugins/node_modules/ace/lib/ace/selection.js @@ -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) { diff --git a/plugins/node_modules/ace/lib/ace/selection_test.js b/plugins/node_modules/ace/lib/ace/selection_test.js index 7760760b..051f8748 100644 --- a/plugins/node_modules/ace/lib/ace/selection_test.js +++ b/plugins/node_modules/ace/lib/ace/selection_test.js @@ -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); } }; diff --git a/plugins/node_modules/ace/lib/ace/test/all_browser.js b/plugins/node_modules/ace/lib/ace/test/all_browser.js index b5b111f1..10b9ddaf 100644 --- a/plugins/node_modules/ace/lib/ace/test/all_browser.js +++ b/plugins/node_modules/ace/lib/ace/test/all_browser.js @@ -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) { diff --git a/plugins/node_modules/ace/lib/ace/theme/dracula.css b/plugins/node_modules/ace/lib/ace/theme/dracula.css index 17d7df82..30365c14 100644 --- a/plugins/node_modules/ace/lib/ace/theme/dracula.css +++ b/plugins/node_modules/ace/lib/ace/theme/dracula.css @@ -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 +} \ No newline at end of file diff --git a/plugins/node_modules/ace/lib/ace/theme/dracula.js b/plugins/node_modules/ace/lib/ace/theme/dracula.js index 24b0e5dc..f3b7b328 100644 --- a/plugins/node_modules/ace/lib/ace/theme/dracula.js +++ b/plugins/node_modules/ace/lib/ace/theme/dracula.js @@ -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); diff --git a/plugins/node_modules/ace/lib/ace/theme/textmate.js b/plugins/node_modules/ace/lib/ace/theme/textmate.js index 75e19745..be952da7 100644 --- a/plugins/node_modules/ace/lib/ace/theme/textmate.js +++ b/plugins/node_modules/ace/lib/ace/theme/textmate.js @@ -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); diff --git a/plugins/node_modules/ace/lib/ace/tooltip.js b/plugins/node_modules/ace/lib/ace/tooltip.js index d3ee2c3d..cc17e6e5 100644 --- a/plugins/node_modules/ace/lib/ace/tooltip.js +++ b/plugins/node_modules/ace/lib/ace/tooltip.js @@ -69,7 +69,7 @@ function Tooltip (parentNode) { * @param {String} text **/ this.setText = function(text) { - dom.setInnerText(this.getElement(), text); + this.getElement().textContent = text; }; /** diff --git a/plugins/node_modules/ace/lib/ace/undomanager.js b/plugins/node_modules/ace/lib/ace/undomanager.js index 4e94ccb8..2091058a 100644 --- a/plugins/node_modules/ace/lib/ace/undomanager.js +++ b/plugins/node_modules/ace/lib/ace/undomanager.js @@ -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]; diff --git a/plugins/node_modules/ace/lib/ace/virtual_renderer.js b/plugins/node_modules/ace/lib/ace/virtual_renderer.js index ef5f68c2..87ee6ad3 100644 --- a/plugins/node_modules/ace/lib/ace/virtual_renderer.js +++ b/plugins/node_modules/ace/lib/ace/virtual_renderer.js @@ -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: { } }); diff --git a/plugins/node_modules/ace/lib/ace/virtual_renderer_test.js b/plugins/node_modules/ace/lib/ace/virtual_renderer_test.js index a694e9c9..3bb98685 100644 --- a/plugins/node_modules/ace/lib/ace/virtual_renderer_test.js +++ b/plugins/node_modules/ace/lib/ace/virtual_renderer_test.js @@ -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)