Merge master, update content

This commit is contained in:
Garen Torikian 2012-04-16 21:14:50 -07:00
commit c2caee8024
79 changed files with 3178 additions and 767 deletions

View file

@ -220,7 +220,7 @@ function buildAce(aceProject, options) {
"css", "html", "javascript", "php", "coldfusion", "python", "lua", "xml", "ruby", "java", "c_cpp",
"coffee", "perl", "csharp", "haxe", "liquid", "svg", "clojure", "scss", "json", "groovy",
"ocaml", "scala", "textile", "scad", "markdown", "latex", "powershell", "sql",
"text", "pgsql", "sh", "xquery"
"text", "pgsql", "sh", "xquery", "less"
],
themes: [
"chrome", "clouds", "clouds_midnight", "cobalt", "crimson_editor", "dawn",

View file

@ -39,9 +39,10 @@
define(function(require, exports, module) {
"use strict";
require("ace/lib/fixoldbrowsers");
require("ace/config").init();
require("ace/config").init();
var env = {};
var event = require("ace/lib/event");
@ -53,9 +54,12 @@ var vim = require("ace/keyboard/keybinding/vim").Vim;
var emacs = require("ace/keyboard/keybinding/emacs").Emacs;
var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
var modesByName;
// workers do not work for file:
if (location.protocol == "file:")
EditSession.prototype.$useWorker = false;
var Doc = function(name, desc, file) {
this.name = name;
this.desc = desc;
@ -96,6 +100,7 @@ var modes = [
new Mode("javascript", "JavaScript", ["js"]),
new Mode("json", "JSON", ["json"]),
new Mode("latex", "LaTeX", ["tex"]),
new Mode("less", "LESS", ["less"]),
new Mode("lua", "Lua", ["lua"]),
new Mode("liquid", "Liquid", ["liquid"]),
new Mode("markdown", "Markdown", ["md", "markdown"]),
@ -149,6 +154,10 @@ var docs = [
"scss", "SCSS",
require("ace/requirejs/text!./docs/scss.scss")
),
new Doc(
"less", "LESS",
require("ace/requirejs/text!./docs/less.less")
),
new Doc(
"html", "HTML",
require("ace/requirejs/text!./docs/html.html")
@ -301,6 +310,7 @@ var showGutterEl = document.getElementById("show_gutter");
var showPrintMarginEl = document.getElementById("show_print_margin");
var highlightSelectedWordE = document.getElementById("highlight_selected_word");
var showHScrollEl = document.getElementById("show_hscroll");
var animateScrollEl = document.getElementById("animate_scroll");
var softTabEl = document.getElementById("soft_tab");
var behavioursEl = document.getElementById("enable_behaviours");
@ -318,14 +328,19 @@ modes.forEach(function(mode) {
modeEl.appendChild(option);
});
bindDropdown("mode", function(value) {
env.editor.getSession().setMode(modesByName[value].mode || modesByName.text.mode);
env.editor.getSession().modeName = value;
});
bindDropdown("doc", function(value) {
var doc = docsByName[value].doc;
if (!docsByName[value].initialized) {
docsByName[value].initialized = true;
doc.setMode(modesByName[docsByName[value].name].mode);
}
var session = env.split.setSession(doc);
session.name = doc.name;
@ -338,39 +353,47 @@ function updateUIEditorOptions() {
var editor = env.editor;
var session = editor.session;
docEl.value = session.name;
modeEl.value = session.modeName || "text";
session.setFoldStyle(foldingEl.value);
if (!session.getUseWrapMode()) {
wrapModeEl.value = "off";
} else {
wrapModeEl.value = session.getWrapLimitRange().min || "free";
}
saveOption(docEl, session.name);
saveOption(modeEl, session.modeName || "text");
saveOption(wrapModeEl, session.getUseWrapMode() ? session.getWrapLimitRange().min || "free" : "off");
selectStyleEl.checked = editor.getSelectionStyle() == "line";
themeEl.value = editor.getTheme();
highlightActiveEl.checked = editor.getHighlightActiveLine();
showHiddenEl.checked = editor.getShowInvisibles();
showGutterEl.checked = editor.renderer.getShowGutter();
showPrintMarginEl.checked = editor.renderer.getShowPrintMargin();
highlightSelectedWordE.checked = editor.getHighlightSelectedWord();
showHScrollEl.checked = editor.renderer.getHScrollBarAlwaysVisible();
softTabEl.checked = session.getUseSoftTabs();
behavioursEl.checked = editor.getBehavioursEnabled();
saveOption(selectStyleEl, editor.getSelectionStyle() == "line");
saveOption(themeEl, editor.getTheme());
saveOption(highlightActiveEl, editor.getHighlightActiveLine());
saveOption(showHiddenEl, editor.getShowInvisibles());
saveOption(showGutterEl, editor.renderer.getShowGutter());
saveOption(showPrintMarginEl, editor.renderer.getShowPrintMargin());
saveOption(highlightSelectedWordE, editor.getHighlightSelectedWord());
saveOption(showHScrollEl, editor.renderer.getHScrollBarAlwaysVisible());
saveOption(animateScrollEl, editor.getAnimatedScroll());
saveOption(softTabEl, session.getUseSoftTabs());
saveOption(behavioursEl, editor.getBehavioursEnabled());
}
bindDropdown("mode", function(value) {
env.editor.getSession().setMode(modesByName[value].mode || modesByName.text.mode);
env.editor.getSession().modeName = value;
});
function saveOption(el, val) {
if (!el.onchange || el.onclick)
return;
if ("checked" in el) {
if (val !== undefined)
el.checked = val;
localStorage && localStorage.setItem(el.id, el.checked ? 1 : 0);
}
else {
if (val !== undefined)
el.value = val;
localStorage && localStorage.setItem(el.id, el.value);
}
}
bindDropdown("theme", function(value) {
if (!value)
return;
env.editor.setTheme(value);
env.editor.setTheme(value);
});
bindDropdown("keybinding", function(value) {
@ -440,6 +463,10 @@ bindCheckbox("show_hscroll", function(checked) {
env.editor.renderer.setHScrollBarAlwaysVisible(checked);
});
bindCheckbox("animate_scroll", function(checked) {
env.editor.setAnimatedScroll(checked);
});
bindCheckbox("soft_tab", function(checked) {
env.editor.getSession().setUseSoftTabs(checked);
});
@ -448,6 +475,7 @@ bindCheckbox("enable_behaviours", function(checked) {
env.editor.setBehavioursEnabled(checked);
});
var secondSession = null;
bindDropdown("split", function(value) {
var sp = env.split;
@ -475,8 +503,12 @@ bindDropdown("split", function(value) {
function bindCheckbox(id, callback) {
var el = document.getElementById(id);
if (localStorage && localStorage.getItem(id))
el.checked = localStorage.getItem(id) == "1";
var onCheck = function() {
callback(!!el.checked);
saveOption(el);
};
el.onclick = onCheck;
onCheck();
@ -484,9 +516,14 @@ function bindCheckbox(id, callback) {
function bindDropdown(id, callback) {
var el = document.getElementById(id);
if (localStorage && localStorage.getItem(id))
el.value = localStorage.getItem(id);
var onChange = function() {
callback(el.value);
saveOption(el);
};
el.onchange = onChange;
onChange();
}
@ -497,7 +534,6 @@ function onResize() {
container.style.width = width + "px";
container.style.height = document.documentElement.clientHeight + "px";
env.split.resize();
// env.editor.resize();
}
window.onresize = onResize;
@ -578,4 +614,7 @@ commands.addCommand({
}
});
// add multiple cursor support to editor
require("ace/multi_select").MultiSelect(env.editor);
});

View file

@ -1,4 +1,4 @@
function foo (items, nada) {
function foo(items, nada) {
for (var i=0; i<items.length; i++) {
alert(items[i] + "juhu\n");
} // Real Tab.

View file

@ -0,0 +1,28 @@
/* styles.less */
@base: #f938ab;
.box-shadow(@style, @c) when (iscolor(@c)) {
box-shadow: @style @c;
-webkit-box-shadow: @style @c;
-moz-box-shadow: @style @c;
}
.box-shadow(@style, @alpha: 50%) when (isnumber(@alpha)) {
.box-shadow(@style, rgba(0, 0, 0, @alpha));
}
// Box styles
.box {
color: saturate(@base, 5%);
border-color: lighten(@base, 30%);
div { .box-shadow(0 0 5px, 30%) }
a {
color: @base;
&:hover {
color: lighten(@base, 50%);
}
}
}

@ -1 +1 @@
Subproject commit fadf80529983183e3e4bf01f90e014c1c16f223b
Subproject commit d2a65d0addc2e5ab922bbff9cb6022a4652b4f13

View file

@ -7,12 +7,12 @@
<title>Ace Kitchen Sink</title>
<meta name="author" content="Fabian Jakobs">
<link rel="stylesheet" href="demo/kitchen-sink/styles.css" type="text/css" media="screen" charset="utf-8">
<!--
<!--
Ace
version %version%
commit %commit%
-->
</head>
<body>
@ -132,6 +132,13 @@
<input type="checkbox" name="show_hscroll" id="show_hscroll">
</td>
</tr>
<tr>
<td >
<label for="animate_scroll">Animate scrolling</label>
</td><td>
<input type="checkbox" name="animate_scroll" id="animate_scroll">
</td>
</tr>
<tr>
<td >
<label for="keybinding">Key Binding</label>
@ -210,7 +217,7 @@
<script src="demo/kitchen-sink/require.js" data-main="demo/kitchen-sink/demo" type="text/javascript"></script>
<!--DEVEL -->
<!--PACKAGE
<script src="demo/kitchen-sink/kitchen-sink-uncompressed.js" data-ace-suffix="-uncompressed.js" data-ace-base="demo/kitchen-sink" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">

View file

@ -55,12 +55,12 @@ var Editor = require("./editor").Editor;
var EditSession = require("./edit_session").EditSession;
var UndoManager = require("./undomanager").UndoManager;
var Renderer = require("./virtual_renderer").VirtualRenderer;
var MultiSelect = require("./multi_select").MultiSelect;
// The following require()s are for inclusion in the built ace file
require("./worker/worker_client");
require("./keyboard/hash_handler");
require("./keyboard/state_handler");
require("./lib/net");
require("./placeholder");
require("./config").init();
@ -81,6 +81,7 @@ exports.edit = function(el) {
el.innerHTML = '';
var editor = new Editor(new Renderer(el, require("./theme/textmate")));
new MultiSelect(editor);
editor.setSession(doc);
var env = {};

View file

@ -1,7 +1,9 @@
define(function(require, exports, module) {
"use strict";
var keyUtil = require("../lib/keys");
var oop = require("../lib/oop");
var HashHandler = require("../keyboard/hash_handler").HashHandler;
var EventEmitter = require("../lib/event_emitter").EventEmitter;
/**
* class CommandManager
@ -22,128 +24,22 @@ var keyUtil = require("../lib/keys");
**/
var CommandManager = function(platform, commands) {
if (typeof platform !== "string")
throw new TypeError("'platform' argument must be either 'mac' or 'win'");
this.platform = platform;
this.commands = {};
this.commmandKeyBinding = {};
if (commands)
commands.forEach(this.addCommand, this);
this.addCommands(commands);
this.setDefaultHandler("exec", function(e) {
e.command.exec(e.editor, e.args || {});
});
};
oop.inherits(CommandManager, HashHandler);
(function() {
this.addCommand = function(command) {
if (this.commands[command.name])
this.removeCommand(command);
this.commands[command.name] = command;
if (command.bindKey) {
this._buildKeyHash(command);
}
};
this.removeCommand = function(command) {
var name = (typeof command === 'string' ? command : command.name);
command = this.commands[name];
delete this.commands[name];
// exaustive search is brute force but since removeCommand is
// not a performance critical operation this should be OK
var ckb = this.commmandKeyBinding;
for (var hashId in ckb) {
for (var key in ckb[hashId]) {
if (ckb[hashId][key] == command)
delete ckb[hashId][key];
}
}
};
this.addCommands = function(commands) {
Object.keys(commands).forEach(function(name) {
var command = commands[name];
if (typeof command === "string")
return this.bindKey(command, name);
if (typeof command === "function")
command = { exec: command };
if (!command.name)
command.name = name;
this.addCommand(command);
}, this);
};
this.removeCommands = function(commands) {
Object.keys(commands).forEach(function(name) {
this.removeCommand(commands[name]);
}, this);
};
this.bindKey = function(key, command) {
if(!key)
return;
var ckb = this.commmandKeyBinding;
key.split("|").forEach(function(keyPart) {
var binding = parseKeys(keyPart, command);
var hashId = binding.hashId;
(ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command;
});
};
this.bindKeys = function(keyList) {
Object.keys(keyList).forEach(function(key) {
this.bindKey(key, keyList[key]);
}, this);
};
this._buildKeyHash = function(command) {
var binding = command.bindKey;
if (!binding)
return;
var key = typeof binding == "string" ? binding: binding[this.platform];
this.bindKey(key, command);
};
function parseKeys(keys, val, ret) {
var key;
var hashId = 0;
var parts = splitSafe(keys);
for (var i=0, l = parts.length; i < l; i++) {
if (keyUtil.KEY_MODS[parts[i]])
hashId = hashId | keyUtil.KEY_MODS[parts[i]];
else
key = parts[i] || "-"; //when empty, the splitSafe removed a '-'
}
return {
key: key,
hashId: hashId
};
}
function splitSafe(s) {
return (s.toLowerCase()
.trim()
.split(new RegExp("[\\s ]*\\-[\\s ]*", "g"), 999));
}
this.findKeyCommand = function findKeyCommand(hashId, textOrKey) {
// Convert keyCode to the string representation.
if (typeof textOrKey == "number") {
textOrKey = keyUtil.keyCodeToString(textOrKey);
}
var ckbr = this.commmandKeyBinding;
return ckbr[hashId] && ckbr[hashId][textOrKey.toLowerCase()];
};
oop.implement(this, EventEmitter);
this.exec = function(command, editor, args) {
if (typeof command === 'string')
@ -155,7 +51,7 @@ var CommandManager = function(platform, commands) {
if (editor && editor.$readOnly && !command.readOnly)
return false;
command.exec(editor, args || {});
this._emit("exec", {editor: editor, command: command, args: args});
return true;
};
@ -164,20 +60,22 @@ var CommandManager = function(platform, commands) {
return;
if (this.recording) {
this.macro.pop();
this.exec = this.normal_exec;
this.removeEventListener("exec", this.$addCommandToMacro);
if (!this.macro.length)
this.macro = this.oldMacro;
return this.recording = false;
}
if (!this.$addCommandToMacro) {
this.$addCommandToMacro = function(e) {
this.macro.push([e.command, e.args]);
}.bind(this);
}
this.oldMacro = this.macro;
this.macro = [];
this.normal_exec = this.exec;
this.exec = function(command, editor, args) {
this.macro.push([command, args]);
return this.normal_exec(command, editor, args);
};
this.on("exec", this.$addCommandToMacro);
return this.recording = true;
};

View file

@ -127,91 +127,109 @@ exports.commands = [{
name: "selectup",
bindKey: bindKey("Shift-Up", "Shift-Up"),
exec: function(editor) { editor.getSelection().selectUp(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "golineup",
bindKey: bindKey("Up", "Up|Ctrl-P"),
exec: function(editor, args) { editor.navigateUp(args.times); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selecttoend",
bindKey: bindKey("Ctrl-Shift-End|Alt-Shift-Down", "Command-Shift-Down"),
exec: function(editor) { editor.getSelection().selectFileEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotoend",
bindKey: bindKey("Ctrl-End|Ctrl-Down", "Command-End|Command-Down"),
exec: function(editor) { editor.navigateFileEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectdown",
bindKey: bindKey("Shift-Down", "Shift-Down"),
exec: function(editor) { editor.getSelection().selectDown(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "golinedown",
bindKey: bindKey("Down", "Down|Ctrl-N"),
exec: function(editor, args) { editor.navigateDown(args.times); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectwordleft",
bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"),
exec: function(editor) { editor.getSelection().selectWordLeft(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotowordleft",
bindKey: bindKey("Ctrl-Left", "Option-Left"),
exec: function(editor) { editor.navigateWordLeft(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selecttolinestart",
bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"),
exec: function(editor) { editor.getSelection().selectLineStart(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotolinestart",
bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"),
exec: function(editor) { editor.navigateLineStart(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectleft",
bindKey: bindKey("Shift-Left", "Shift-Left"),
exec: function(editor) { editor.getSelection().selectLeft(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotoleft",
bindKey: bindKey("Left", "Left|Ctrl-B"),
exec: function(editor, args) { editor.navigateLeft(args.times); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectwordright",
bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"),
exec: function(editor) { editor.getSelection().selectWordRight(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotowordright",
bindKey: bindKey("Ctrl-Right", "Option-Right"),
exec: function(editor) { editor.navigateWordRight(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selecttolineend",
bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"),
exec: function(editor) { editor.getSelection().selectLineEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotolineend",
bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"),
exec: function(editor) { editor.navigateLineEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectright",
bindKey: bindKey("Shift-Right", "Shift-Right"),
exec: function(editor) { editor.getSelection().selectRight(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "gotoright",
bindKey: bindKey("Right", "Right|Ctrl-F"),
exec: function(editor, args) { editor.navigateRight(args.times); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectpagedown",
@ -247,11 +265,13 @@ exports.commands = [{
name: "selectlinestart",
bindKey: bindKey("Shift-Home", "Shift-Home"),
exec: function(editor) { editor.getSelection().selectLineStart(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "selectlineend",
bindKey: bindKey("Shift-End", "Shift-End"),
exec: function(editor) { editor.getSelection().selectLineEnd(); },
multiSelectAction: "forEach",
readOnly: true
}, {
name: "togglerecording",
@ -267,18 +287,33 @@ exports.commands = [{
name: "jumptomatching",
bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"),
exec: function(editor) { editor.jumpToMatching(); },
multiSelectAction: "forEach",
readOnly: true
},
// commands disabled in readOnly mode
{
name: "cut",
exec: function(editor) {
var range = editor.getSelectionRange();
editor._emit("cut", range);
if (!editor.selection.isEmpty()) {
editor.session.remove(range);
editor.clearSelection();
}
},
multiSelectAction: "forEach"
}, {
name: "removeline",
bindKey: bindKey("Ctrl-D", "Command-D"),
exec: function(editor) { editor.removeLines(); }
exec: function(editor) { editor.removeLines(); },
multiSelectAction: "forEach"
}, {
name: "togglecomment",
bindKey: bindKey("Ctrl-7", "Command-7"),
exec: function(editor) { editor.toggleCommentLines(); }
exec: function(editor) { editor.toggleCommentLines(); },
multiSelectAction: "forEach"
}, {
name: "replace",
bindKey: bindKey("Ctrl-R", "Command-Option-F"),
@ -330,62 +365,76 @@ exports.commands = [{
}, {
name: "del",
bindKey: bindKey("Delete", "Delete|Ctrl-D"),
exec: function(editor) { editor.remove("right"); }
exec: function(editor) { editor.remove("right"); },
multiSelectAction: "forEach"
}, {
name: "backspace",
bindKey: bindKey(
"Command-Backspace|Option-Backspace|Shift-Backspace|Backspace",
"Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"
),
exec: function(editor) { editor.remove("left"); }
exec: function(editor) { editor.remove("left"); },
multiSelectAction: "forEach"
}, {
name: "removetolinestart",
bindKey: bindKey("Alt-Backspace", "Command-Backspace"),
exec: function(editor) { editor.removeToLineStart(); }
exec: function(editor) { editor.removeToLineStart(); },
multiSelectAction: "forEach"
}, {
name: "removetolineend",
bindKey: bindKey("Alt-Delete", "Ctrl-K"),
exec: function(editor) { editor.removeToLineEnd(); }
exec: function(editor) { editor.removeToLineEnd(); },
multiSelectAction: "forEach"
}, {
name: "removewordleft",
bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"),
exec: function(editor) { editor.removeWordLeft(); }
exec: function(editor) { editor.removeWordLeft(); },
multiSelectAction: "forEach"
}, {
name: "removewordright",
bindKey: bindKey("Ctrl-Delete", "Alt-Delete"),
exec: function(editor) { editor.removeWordRight(); }
exec: function(editor) { editor.removeWordRight(); },
multiSelectAction: "forEach"
}, {
name: "outdent",
bindKey: bindKey("Shift-Tab", "Shift-Tab"),
exec: function(editor) { editor.blockOutdent(); }
exec: function(editor) { editor.blockOutdent(); },
multiSelectAction: "forEach"
}, {
name: "indent",
bindKey: bindKey("Tab", "Tab"),
exec: function(editor) { editor.indent(); }
exec: function(editor) { editor.indent(); },
multiSelectAction: "forEach"
}, {
name: "insertstring",
exec: function(editor, str) { editor.insert(str); }
exec: function(editor, str) { editor.insert(str); },
multiSelectAction: "forEach"
}, {
name: "inserttext",
exec: function(editor, args) {
editor.insert(lang.stringRepeat(args.text || "", args.times || 1));
}
},
multiSelectAction: "forEach"
}, {
name: "splitline",
bindKey: bindKey(null, "Ctrl-O"),
exec: function(editor) { editor.splitLine(); }
exec: function(editor) { editor.splitLine(); },
multiSelectAction: "forEach"
}, {
name: "transposeletters",
bindKey: bindKey("Ctrl-T", "Ctrl-T"),
exec: function(editor) { editor.transposeLetters(); }
exec: function(editor) { editor.transposeLetters(); },
multiSelectAction: function(editor) {editor.transposeSelections(1); }
}, {
name: "touppercase",
bindKey: bindKey("Ctrl-U", "Ctrl-U"),
exec: function(editor) { editor.toUpperCase(); }
exec: function(editor) { editor.toUpperCase(); },
multiSelectAction: "forEach"
}, {
name: "tolowercase",
bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"),
exec: function(editor) { editor.toLowerCase(); }
exec: function(editor) { editor.toLowerCase(); },
multiSelectAction: "forEach"
}];
});

View file

@ -0,0 +1,100 @@
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Harutyun Amirjanyan <amirjanyan AT gmail DOT com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
// commands to enter multiselect mode
exports.defaultCommands = [{
name: "addCursorAbove",
exec: function(editor) { editor.selectMoreLines(-1); },
bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"},
readonly: true
}, {
name: "addCursorBelow",
exec: function(editor) { editor.selectMoreLines(1); },
bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"},
readonly: true
}, {
name: "addCursorAboveSkipCurrent",
exec: function(editor) { editor.selectMoreLines(-1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"},
readonly: true
}, {
name: "addCursorBelowSkipCurrent",
exec: function(editor) { editor.selectMoreLines(1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"},
readonly: true
}, {
name: "selectMoreBefore",
exec: function(editor) { editor.selectMore(-1); },
bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"},
readonly: true
}, {
name: "selectMoreAfter",
exec: function(editor) { editor.selectMore(1); },
bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"},
readonly: true
}, {
name: "selectNextBefore",
exec: function(editor) { editor.selectMore(-1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"},
readonly: true
}, {
name: "selectNextAfter",
exec: function(editor) { editor.selectMore(1, true); },
bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"},
readonly: true
}, {
name: "splitIntoLines",
exec: function(editor) { editor.multiSelect.splitIntoLines(); },
bindKey: {win: "Ctrl-Shift-L", mac: "Ctrl-Shift-L"},
readonly: true
}];
// commands active in multiselect mode
exports.multiEditCommands = [{
name: "singleSelection",
bindKey: "esc",
exec: function(editor) { editor.exitMultiSelectMode(); },
readonly: true
}];
var HashHandler = require("../keyboard/hash_handler").HashHandler;
exports.keyboardHandler = new HashHandler(exports.multiEditCommands);
});

View file

@ -1,6 +1,5 @@
@import url(//fonts.googleapis.com/css?family=Droid+Sans+Mono);
.ace_editor {
position: absolute;
overflow: hidden;
@ -35,6 +34,11 @@
height: 100%;
width: auto;
cursor: default;
z-index: 1000;
}
.ace_gutter.horscroll {
box-shadow: 0px 0px 20px rgba(0,0,0,0.4);
}
.ace_gutter-cell {
@ -147,6 +151,10 @@
opacity: 0.2;
}
.ace_editor.multiselect .ace_cursor {
border-left-width: 1px;
}
.ace_line {
white-space: nowrap;
}
@ -158,12 +166,12 @@
.ace_marker-layer .ace_selection {
position: absolute;
z-index: 4;
z-index: 5;
}
.ace_marker-layer .ace_bracket {
position: absolute;
z-index: 5;
z-index: 6;
}
.ace_marker-layer .ace_active_line {
@ -171,9 +179,13 @@
z-index: 2;
}
.ace_gutter .ace_gutter_active_line{
background-color : #dcdcdc;
}
.ace_marker-layer .ace_selected_word {
position: absolute;
z-index: 6;
z-index: 4;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;

View file

@ -1998,8 +1998,8 @@ var EditSession = function(text, mode) {
* Returns the column position (on screen) for the last character in the provided row.
**/
this.getScreenLastRowColumn = function(screenRow) {
//return this.screenToDocumentColumn(screenRow, Number.MAX_VALUE / 10)
return this.documentToScreenColumn(screenRow, this.doc.getLine(screenRow).length);
var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE)
return this.documentToScreenColumn(pos.row, pos.column);
};
/** internal
@ -2153,16 +2153,10 @@ var EditSession = function(text, mode) {
docColumn += this.$getStringScreenWidth(line, screenColumn)[1];
// Need to do some clamping action here.
if (this.$useWrapMode) {
if (docColumn >= column) {
// We remove one character at the end such that the docColumn
// position returned is not associated to the next row on the
// screen.
docColumn = column - 1;
}
} else {
docColumn = Math.min(docColumn, line.length);
// We remove one character at the end so that the docColumn
// position returned is not associated to the next row on the screen.
if (this.$useWrapMode && docColumn >= column) {
docColumn = column - 1;
}
if (foldLine) {

View file

@ -76,7 +76,7 @@ var Fold = exports.Fold = function(range, placeholder) {
};
this.addSubFold = function(fold) {
if (this.range.isEequal(fold))
if (this.range.isEqual(fold))
return this;
if (!this.range.containsRange(fold))

View file

@ -714,7 +714,7 @@ function Folding() {
// sometimes singleline folds can be missed by the code above
if (!range.isMultiLine()) {
fold = this.getFoldAt(range.start.row, range.start.column, 1);
if (fold && range.isEequal(fold.range)) {
if (fold && range.isEqual(fold.range)) {
this.removeFold(fold);
return;
}

View file

@ -77,7 +77,7 @@ var Editor = function(renderer, session) {
var container = renderer.getContainerElement();
this.container = container;
this.renderer = renderer;
this.textInput = new TextInput(renderer.getTextAreaContainer(), this);
this.keyBinding = new KeyBinding(this);
@ -445,11 +445,7 @@ var Editor = function(renderer, session) {
this.renderer.updateCursor();
if (!this.$blockScrolling) {
var selection = this.getSelection();
if (selection.isEmpty())
this.renderer.scrollCursorIntoView(selection.getCursor());
else
this.renderer.scrollSelectionIntoView(selection.getSelectionLead(), selection.getSelectionAnchor());
this.renderer.scrollCursorIntoView();
}
// move text input over the cursor
@ -468,14 +464,19 @@ var Editor = function(renderer, session) {
this.$updateHighlightActiveLine = function() {
var session = this.getSession();
if (session.$highlightLineMarker) {
if (session.$highlightLineMarker)
session.removeMarker(session.$highlightLineMarker);
}
session.$highlightLineMarker = null;
if (typeof this.$lastrow == "number")
this.renderer.removeGutterDecoration(this.$lastrow, "ace_gutter_active_line");
if (this.getHighlightActiveLine() && (this.getSelectionStyle() != "line" || !this.selection.isMultiLine())) {
session.$highlightLineMarker = null;
this.$lastrow = null;
if (this.getHighlightActiveLine()) {
var cursor = this.getCursorPosition(),
foldLine = this.session.getFoldLine(cursor.row);
if ((this.getSelectionStyle() != "line" || !this.selection.isMultiLine())) {
var range;
if (foldLine) {
range = new Range(foldLine.start.row, 0, foldLine.end.row + 1, 0);
@ -484,6 +485,9 @@ var Editor = function(renderer, session) {
}
session.$highlightLineMarker = session.addMarker(range, "ace_active_line", "background");
}
this.renderer.addGutterDecoration(this.$lastrow = cursor.row, "ace_gutter_active_line");
}
};
/**
@ -603,21 +607,12 @@ var Editor = function(renderer, session) {
};
/**
* Editor@onCut()
* Editor.onCut()
*
* Emitted whenever a text "cut" happens.
**/
this.onCut = function() {
if (this.$readOnly)
return;
var range = this.getSelectionRange();
this._emit("cut", range);
if (!this.selection.isEmpty()) {
this.session.remove(range);
this.clearSelection();
}
this.commands.exec("cut", this);
};
/**
@ -1005,7 +1000,7 @@ var Editor = function(renderer, session) {
this.$showFoldWidgets = show;
this.renderer.updateFull();
};
/**
* Editor.getShowFoldWidgets() -> Boolean
*
@ -1356,7 +1351,7 @@ var Editor = function(renderer, session) {
range.start.row += linesMoved;
range.end.row += linesMoved;
selection.setSelectionRange(range, reverse);
}
}
else {
selection.setSelectionAnchor(rows.last+linesMoved+1, 0);
selection.$moveSelection(function() {
@ -1674,13 +1669,13 @@ var Editor = function(renderer, session) {
cursor.column -= 2;
pos = this.session.findMatchingBracket(cursor);
}
if (pos) {
this.clearSelection();
this.moveCursorTo(pos.row, pos.column);
}
};
/**
* Editor.gotoLine(lineNumber, column) -> Void
* - lineNumber (Number): The line number to go to
@ -1849,12 +1844,19 @@ var Editor = function(renderer, session) {
this.$search.set(options);
var range = this.$search.find(this.session);
var replaced = 0;
if (!range)
return;
return replaced;
this.$tryReplace(range, replacement);
if (range !== null)
if (this.$tryReplace(range, replacement)) {
replaced = 1;
}
if (range !== null) {
this.selection.setSelectionRange(range);
this.renderer.scrollSelectionIntoView(range.start, range.end);
}
return replaced;
};
/**
@ -1870,19 +1872,26 @@ var Editor = function(renderer, session) {
}
var ranges = this.$search.findAll(this.session);
var replaced = 0;
if (!ranges.length)
return;
return replaced;
this.$blockScrolling += 1;
var selection = this.getSelectionRange();
this.clearSelection();
this.selection.moveCursorTo(0, 0);
this.$blockScrolling += 1;
for (var i = ranges.length - 1; i >= 0; --i)
this.$tryReplace(ranges[i], replacement);
for (var i = ranges.length - 1; i >= 0; --i) {
if(this.$tryReplace(ranges[i], replacement)) {
replaced++;
}
}
this.selection.setSelectionRange(selection);
this.$blockScrolling -= 1;
return replaced;
};
this.$tryReplace = function(range, replacement) {
@ -1956,7 +1965,23 @@ var Editor = function(renderer, session) {
var range = this.$search.find(this.session);
if (range) {
this.session.unfold(range);
this.selection.setSelectionRange(range); // this scrolls selection into view
this.$blockScrolling += 1;
this.selection.setSelectionRange(range);
this.$blockScrolling -= 1;
if (this.getAnimatedScroll()) {
var cursor = this.getCursorPosition();
if (!this.isRowFullyVisible(cursor.row))
this.scrollToLine(cursor.row, true);
//@todo scroll X
//if (!this.isColumnFullyVisible(cursor.column))
//this.scrollToRow(cursor.column);
}
else {
this.renderer.scrollSelectionIntoView(range.start, range.end);
}
}
};
@ -1991,4 +2016,4 @@ var Editor = function(renderer, session) {
exports.Editor = Editor;
});
});

View file

@ -41,77 +41,127 @@ define(function(require, exports, module) {
var keyUtil = require("../lib/keys");
function HashHandler(config) {
this.setConfig(config);
}
function HashHandler(config, platform) {
this.platform = platform;
this.commands = {};
this.commmandKeyBinding = {};
this.addCommands(config);
};
(function() {
function splitSafe(s, separator, limit, bLowerCase) {
return (bLowerCase && s.toLowerCase() || s)
.replace(/(?:^\s+|\n|\s+$)/g, "")
.split(new RegExp("[\\s ]*" + separator + "[\\s ]*", "g"), limit || 999);
}
this.addCommand = function(command) {
if (this.commands[command.name])
this.removeCommand(command);
this.commands[command.name] = command;
if (command.bindKey) {
this._buildKeyHash(command);
}
};
this.removeCommand = function(command) {
var name = (typeof command === 'string' ? command : command.name);
command = this.commands[name];
delete this.commands[name];
// exhaustive search is brute force but since removeCommand is
// not a performance critical operation this should be OK
var ckb = this.commmandKeyBinding;
for (var hashId in ckb) {
for (var key in ckb[hashId]) {
if (ckb[hashId][key] == command)
delete ckb[hashId][key];
}
}
};
this.addCommands = function(commands) {
commands && Object.keys(commands).forEach(function(name) {
var command = commands[name];
if (typeof command === "string")
return this.bindKey(command, name);
if (typeof command === "function")
command = { exec: command };
if (!command.name)
command.name = name;
this.addCommand(command);
}, this);
};
this.removeCommands = function(commands) {
Object.keys(commands).forEach(function(name) {
this.removeCommand(commands[name]);
}, this);
};
this.bindKey = function(key, command) {
if(!key)
return;
var ckb = this.commmandKeyBinding;
key.split("|").forEach(function(keyPart) {
var binding = parseKeys(keyPart, command);
var hashId = binding.hashId;
(ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command;
});
};
this.bindKeys = function(keyList) {
Object.keys(keyList).forEach(function(key) {
this.bindKey(key, keyList[key]);
}, this);
};
this._buildKeyHash = function(command) {
var binding = command.bindKey;
if (!binding)
return;
var key = typeof binding == "string" ? binding: binding[this.platform];
this.bindKey(key, command);
};
function parseKeys(keys, val, ret) {
var key,
hashId = 0,
parts = splitSafe(keys, "\\-", null, true),
i = 0,
l = parts.length;
var key;
var hashId = 0;
var parts = splitSafe(keys.toLowerCase());
for (; i < l; ++i) {
for (var i = 0, l = parts.length; i < l; i++) {
if (keyUtil.KEY_MODS[parts[i]])
hashId = hashId | keyUtil.KEY_MODS[parts[i]];
else
key = parts[i] || "-"; //when empty, the splitSafe removed a '-'
}
(ret[hashId] || (ret[hashId] = {}))[key] = val;
return ret;
return {
key: key,
hashId: hashId
};
}
function objectReverse(obj, keySplit) {
var i, j, l, key,
ret = {};
for (i in obj) {
key = obj[i];
if (keySplit && typeof key == "string") {
key = key.split(keySplit);
for (j = 0, l = key.length; j < l; ++j)
parseKeys.call(this, key[j], i, ret);
}
else {
parseKeys.call(this, key, i, ret);
}
}
return ret;
function splitSafe(s) {
return (s.trim()
.split(new RegExp("[\\s ]*\\-[\\s ]*", "g"), 999));
}
this.setConfig = function(config) {
this.$config = config;
if (typeof this.$config.reverse == "undefined")
this.$config.reverse = objectReverse.call(this, this.$config, "|");
this.findKeyCommand = function findKeyCommand(hashId, keyString) {
var ckbr = this.commmandKeyBinding;
return ckbr[hashId] && ckbr[hashId][keyString.toLowerCase()];
}
this.handleKeyboard = function(data, hashId, keyString, keyCode) {
return {
command: this.findKeyCommand(hashId, keyString)
};
};
/*
* This function is called by keyBinding.
*/
this.handleKeyboard = function(data, hashId, textOrKey, keyCode) {
// Figure out if a commandKey was pressed or just some text was insert.
if (hashId != 0 || keyCode != 0) {
return {
command: (this.$config.reverse[hashId] || {})[textOrKey]
}
} else {
return {
command: "inserttext",
args: {
text: textOrKey
}
}
}
}
}).call(HashHandler.prototype)
exports.HashHandler = HashHandler;
});
});

View file

@ -47,11 +47,10 @@ var Cursor = function(parentEl) {
this.element.className = "ace_layer ace_cursor-layer";
parentEl.appendChild(this.element);
this.cursor = dom.createElement("div");
this.cursor.className = "ace_cursor ace_hidden";
this.element.appendChild(this.cursor);
this.isVisible = false;
this.cursors = [];
this.cursor = this.addCursor();
};
(function() {
@ -65,30 +64,54 @@ var Cursor = function(parentEl) {
this.session = session;
};
this.addCursor = function() {
var el = dom.createElement("div");
var className = "ace_cursor";
if (!this.isVisible)
className += " ace_hidden";
if (this.overwrite)
className += " ace_overwrite";
el.className = className;
this.element.appendChild(el);
this.cursors.push(el);
return el;
};
this.removeCursor = function() {
if (this.cursors.length > 1) {
var el = this.cursors.pop();
el.parentNode.removeChild(el);
return el;
}
};
this.hideCursor = function() {
this.isVisible = false;
dom.addCssClass(this.cursor, "ace_hidden");
for (var i = this.cursors.length; i--; )
dom.addCssClass(this.cursors[i], "ace_hidden");
clearInterval(this.blinkId);
};
this.showCursor = function() {
this.isVisible = true;
dom.removeCssClass(this.cursor, "ace_hidden");
this.cursor.style.visibility = "visible";
for (var i = this.cursors.length; i--; )
dom.removeCssClass(this.cursors[i], "ace_hidden");
this.element.style.visibility = "";
this.restartTimer();
};
this.restartTimer = function() {
clearInterval(this.blinkId);
if (!this.isVisible) {
if (!this.isVisible)
return;
}
var cursor = this.cursor;
var element = this.cursors.length == 1 ? this.cursor : this.element;
this.blinkId = setInterval(function() {
cursor.style.visibility = "hidden";
element.style.visibility = "hidden";
setTimeout(function() {
cursor.style.visibility = "visible";
element.style.visibility = "";
}, 400);
}, 1000);
};
@ -118,25 +141,53 @@ var Cursor = function(parentEl) {
this.update = function(config) {
this.config = config;
this.pixelPos = this.getPixelPosition(null, true);
if (this.session.selectionMarkerCount > 0) {
var selections = this.session.$selectionMarkers;
var i = 0, sel, cursorIndex = 0;
this.cursor.style.left = this.pixelPos.left + "px";
this.cursor.style.top = this.pixelPos.top + "px";
this.cursor.style.width = config.characterWidth + "px";
this.cursor.style.height = config.lineHeight + "px";
for (var i = selections.length; i--; ) {
sel = selections[i];
var pixelPos = this.getPixelPosition(sel.cursor, true);
var overwrite = this.session.getOverwrite()
if (overwrite != this.overwrite) {
this.overwrite = overwrite;
if (overwrite)
dom.addCssClass(this.cursor, "ace_overwrite");
else
dom.removeCssClass(this.cursor, "ace_overwrite");
var style = (this.cursors[cursorIndex++] || this.addCursor()).style;
style.left = pixelPos.left + "px";
style.top = pixelPos.top + "px";
style.width = config.characterWidth + "px";
style.height = config.lineHeight + "px";
}
if (cursorIndex > 1)
while (this.cursors.length > cursorIndex)
this.removeCursor();
} else {
var pixelPos = this.getPixelPosition(null, true);
var style = this.cursor.style;
style.left = pixelPos.left + "px";
style.top = pixelPos.top + "px";
style.width = config.characterWidth + "px";
style.height = config.lineHeight + "px";
while (this.cursors.length > 1)
this.removeCursor();
}
var overwrite = this.session.getOverwrite();
if (overwrite != this.overwrite)
this.$setOverite(overwrite);
this.restartTimer();
};
this.$setOverite = function(overwrite) {
this.overwrite = overwrite;
for (var i = this.cursors.length; i--; ) {
if (overwrite)
dom.addCssClass(this.cursors[i], "ace_overwrite");
else
dom.removeCssClass(this.cursors[i], "ace_overwrite");
}
};
this.destroy = function() {
clearInterval(this.blinkId);
}

View file

@ -68,11 +68,11 @@ var Gutter = function(parentEl) {
this.addGutterDecoration = function(row, className){
if (!this.$decorations[row])
this.$decorations[row] = "";
this.$decorations[row] += " ace_" + className;
this.$decorations[row] += " " + className;
};
this.removeGutterDecoration = function(row, className){
this.$decorations[row] = this.$decorations[row].replace(" ace_" + className, "");
this.$decorations[row] = this.$decorations[row].replace(" " + className, "");
};
this.setBreakpoints = function(rows) {

View file

@ -99,7 +99,7 @@ var Marker = function(parentEl) {
}
else {
this.drawSingleLineMarker(
html, range, marker.clazz, config,
html, range, marker.clazz + " start", config,
null, marker.type
);
}
@ -111,8 +111,8 @@ var Marker = function(parentEl) {
return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
};
/*
* Draws a marker, which spans a range of text in a single line
/**
* Draws a marker, which spans a range of text on multiple lines
*/
this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {
// selection start
@ -122,7 +122,7 @@ var Marker = function(parentEl) {
row, range.start.column,
row, this.session.getScreenLastRowColumn(row)
);
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, "text");
this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " start", layerConfig, 1, "text");
// selection end
row = range.end.row;
@ -137,7 +137,7 @@ var Marker = function(parentEl) {
}
};
/*
/**
* Draws a multi line marker, where lines span the full width
*/
this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig, type) {
@ -152,7 +152,7 @@ var Marker = function(parentEl) {
);
stringBuilder.push(
"<div class='", clazz, "' style='",
"<div class='", clazz, " start' style='",
"height:", height, "px;",
"width:", width, "px;",
"top:", top, "px;",
@ -186,8 +186,8 @@ var Marker = function(parentEl) {
);
};
/*
* Draws a marker which covers one single full line
/**
* Draws a marker which covers part or whole width of a single screen line
*/
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength, type) {
var padding = type === "background" ? 0 : this.$padding;
@ -216,4 +216,4 @@ var Marker = function(parentEl) {
exports.Marker = Marker;
});
});

View file

@ -103,7 +103,7 @@ var Text = function(parentEl) {
lineHeight : 1
};
this.$measureSizes = function() {
this.$measureSizes = useragent.isIE || useragent.isOldGecko ? function() {
var n = 1000;
if (!this.$measureNode) {
var measureNode = this.$measureNode = dom.createElement("div");
@ -113,7 +113,7 @@ var Text = function(parentEl) {
style.left = style.top = (-n * 40) + "px";
style.visibility = "hidden";
style.position = "absolute";
style.position = "fixed";
style.overflow = "visible";
style.whiteSpace = "nowrap";
@ -130,7 +130,6 @@ var Text = function(parentEl) {
container = container.parentNode;
container.appendChild(measureNode);
}
}
// Size and width can be null if the editor is not visible or
@ -150,7 +149,46 @@ var Text = function(parentEl) {
// Size and width can be null if the editor is not visible or
// detached from the document
if (size.width == 0 && size.height == 0)
if (size.width == 0 || size.height == 0)
return null;
return size;
}
: function() {
if (!this.$measureNode) {
var measureNode = this.$measureNode = dom.createElement("div");
var style = measureNode.style;
style.width = style.height = "auto";
style.left = style.top = -100 + "px";
style.visibility = "hidden";
style.position = "fixed";
style.overflow = "visible";
style.whiteSpace = "nowrap";
measureNode.innerHTML = "X";
var container = this.element.parentNode;
while (container && !dom.hasCssClass(container, "ace_editor"))
container = container.parentNode;
if (!container)
return this.$measureNode = null;
container.appendChild(measureNode);
}
var rect = this.$measureNode.getBoundingClientRect();
var size = {
height: rect.height,
width: rect.width
};
// Size and width can be null if the editor is not visible or
// detached from the document
if (size.width == 0 || size.height == 0)
return null;
return size;
@ -264,16 +302,16 @@ var Text = function(parentEl) {
};
this.$renderLinesFragment = function(config, firstRow, lastRow) {
var fragment = this.element.ownerDocument.createDocumentFragment(),
row = firstRow,
fold = this.session.getNextFoldLine(row),
foldStart = fold ?fold.start.row :Infinity;
var fragment = this.element.ownerDocument.createDocumentFragment();
var row = firstRow;
var foldLine = this.session.getNextFoldLine(row);
var foldStart = foldLine ? foldLine.start.row : Infinity;
while (true) {
if (row > foldStart) {
row = fold.end.row+1;
fold = this.session.getNextFoldLine(row, fold);
foldStart = fold ?fold.start.row :Infinity;
row = foldLine.end.row+1;
foldLine = this.session.getNextFoldLine(row, foldLine);
foldStart = foldLine ? foldLine.start.row : Infinity;
}
if (row > lastRow)
break;
@ -312,15 +350,15 @@ var Text = function(parentEl) {
var html = [];
var firstRow = config.firstRow, lastRow = config.lastRow;
var row = firstRow,
fold = this.session.getNextFoldLine(row),
foldStart = fold ?fold.start.row :Infinity;
var row = firstRow;
var foldLine = this.session.getNextFoldLine(row);
var foldStart = foldLine ? foldLine.start.row : Infinity;
while (true) {
if (row > foldStart) {
row = fold.end.row+1;
fold = this.session.getNextFoldLine(row, fold);
foldStart = fold ?fold.start.row :Infinity;
row = foldLine.end.row+1;
foldLine = this.session.getNextFoldLine(row, foldLine);
foldStart = foldLine ? foldLine.start.row :Infinity;
}
if (row > lastRow)
break;

View file

@ -72,7 +72,7 @@ var c_cppHighlightRules = function() {
token : "comment",
regex : "\\/\\/.*$"
},
new DocCommentHighlightRules().getStartRule("doc-start"),
DocCommentHighlightRules.getStartRule("doc-start"),
{
token : "comment", // multi line comment
merge : true,
@ -171,7 +171,7 @@ var c_cppHighlightRules = function() {
};
this.embedRules(DocCommentHighlightRules, "doc-",
[ new DocCommentHighlightRules().getEndRule("start") ]);
[ DocCommentHighlightRules.getEndRule("start") ]);
};
oop.inherits(c_cppHighlightRules, TextHighlightRules);

View file

@ -45,31 +45,7 @@ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var CssHighlightRules = function() {
var properties = lang.arrayToMap(
("-moz-appearance|-moz-box-sizing|-webkit-box-sizing|-moz-outline-radius|-moz-transform|-webkit-transform|" +
"appearance|azimuth|background-attachment|background-color|background-image|" +
"background-origin|background-position|background-repeat|background|border-bottom-color|" +
"border-bottom-style|border-bottom-width|border-bottom|border-collapse|" +
"border-color|border-left-color|border-left-style|border-left-width|" +
"border-left|border-right-color|border-right-style|border-right-width|" +
"border-right|border-spacing|border-style|border-top-color|" +
"border-top-style|border-top-width|border-top|border-width|border|" +
"bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|" +
"counter-reset|cue-after|cue-before|cue|cursor|direction|display|" +
"elevation|empty-cells|float|font-family|font-size-adjust|font-size|" +
"font-stretch|font-style|font-variant|font-weight|font|height|left|" +
"letter-spacing|line-height|list-style-image|list-style-position|" +
"list-style-type|list-style|margin-bottom|margin-left|margin-right|" +
"margin-top|marker-offset|margin|marks|max-height|max-width|min-height|" +
"min-width|-moz-border-radius|opacity|orphans|outline-color|outline-offset|outline-radius|" +
"outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|" +
"padding-left|padding-right|padding-top|padding|page-break-after|" +
"page-break-before|page-break-inside|page|pause-after|pause-before|" +
"pause|pitch-range|pitch|play-during|pointer-events|position|quotes|resize|richness|right|" +
"size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|" +
"stress|table-layout|text-align|text-decoration|text-indent|" +
"text-shadow|text-transform|top|transform|unicode-bidi|vertical-align|" +
"visibility|voice-family|volume|white-space|widows|width|word-spacing|" +
"z-index").split("|")
("animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|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|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|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|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index").split("|")
);
var functions = lang.arrayToMap(
@ -77,27 +53,7 @@ var CssHighlightRules = function() {
);
var constants = lang.arrayToMap(
("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|" +
"block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|" +
"char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|" +
"decimal-leading-zero|decimal|default|disabled|disc|" +
"distribute-all-lines|distribute-letter|distribute-space|" +
"distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|" +
"hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|" +
"ideograph-alpha|ideograph-numeric|ideograph-parenthesis|" +
"ideograph-space|inactive|inherit|inline-block|inline|inset|inside|" +
"inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|" +
"keep-all|left|lighter|line-edge|line-through|line|list-item|loose|" +
"lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|" +
"medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|" +
"nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|" +
"overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|" +
"ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|" +
"solid|square|static|strict|super|sw-resize|table-footer-group|" +
"table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|" +
"transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|" +
"vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|" +
"zero").split("|")
("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|font-size|font|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|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero").split("|")
);
var colors = lang.arrayToMap(
@ -115,6 +71,8 @@ var CssHighlightRules = function() {
// regexps are ordered -> the first match is used
var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
var pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b";
var pseudoClasses = "(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b";
var base_ruleset = [
{
@ -122,7 +80,7 @@ var CssHighlightRules = function() {
merge : true,
regex : "\\/\\*",
next : "ruleset_comment"
},{
}, {
token : "string", // single line
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
}, {
@ -130,7 +88,7 @@ var CssHighlightRules = function() {
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
}, {
token : ["constant.numeric", "keyword"],
regex : "(" + numRe + ")(em|ex|px|ch|cm|mm|in|pt|pc|deg|rad|dpi|grad|ms|s|hz|khz|%)"
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|%)"
}, {
token : ["constant.numeric"],
regex : "([0-9]+)"
@ -140,6 +98,12 @@ var CssHighlightRules = function() {
}, {
token : "constant.numeric", // hex3 color
regex : "#[a-f0-9]{3}"
}, {
token : ["punctuation", "entity.other.attribute-name.pseudo-element.css"],
regex : pseudoElements
}, {
token : ["punctuation", "entity.other.attribute-name.pseudo-class.css"],
regex : pseudoClasses
}, {
token : function(value) {
if (properties.hasOwnProperty(value.toLowerCase())) {

View file

@ -69,27 +69,24 @@ var DocCommentHighlightRules = function() {
oop.inherits(DocCommentHighlightRules, TextHighlightRules);
(function() {
this.getStartRule = function(start) {
return {
token : "comment.doc", // doc comment
merge : true,
regex : "\\/\\*(?=\\*)",
next : start
};
};
this.getEndRule = function (start) {
return {
token : "comment.doc", // closing comment
merge : true,
regex : "\\*\\/",
next : start
};
DocCommentHighlightRules.getStartRule = function(start) {
return {
token : "comment.doc", // doc comment
merge : true,
regex : "\\/\\*(?=\\*)",
next : start
};
};
DocCommentHighlightRules.getEndRule = function (start) {
return {
token : "comment.doc", // closing comment
merge : true,
regex : "\\*\\/",
next : start
};
};
}).call(DocCommentHighlightRules.prototype);
exports.DocCommentHighlightRules = DocCommentHighlightRules;

View file

@ -64,7 +64,7 @@ var GroovyHighlightRules = function() {
token : "comment",
regex : "\\/\\/.*$"
},
new DocCommentHighlightRules().getStartRule("doc-start"),
DocCommentHighlightRules.getStartRule("doc-start"),
{
token : "comment", // multi line comment
merge : true,
@ -134,7 +134,7 @@ var GroovyHighlightRules = function() {
};
this.embedRules(DocCommentHighlightRules, "doc-",
[ new DocCommentHighlightRules().getEndRule("start") ]);
[ DocCommentHighlightRules.getEndRule("start") ]);
};
oop.inherits(GroovyHighlightRules, TextHighlightRules);

View file

@ -26,7 +26,7 @@ var HaxeHighlightRules = function() {
token : "comment",
regex : "\\/\\/.*$"
},
new DocCommentHighlightRules().getStartRule("doc-start"),
DocCommentHighlightRules.getStartRule("doc-start"),
{
token : "comment", // multi line comment
regex : "\\/\\*",
@ -95,7 +95,7 @@ var HaxeHighlightRules = function() {
};
this.embedRules(DocCommentHighlightRules, "doc-",
[ new DocCommentHighlightRules().getEndRule("start") ]);
[ DocCommentHighlightRules.getEndRule("start") ]);
};
oop.inherits(HaxeHighlightRules, TextHighlightRules);

View file

@ -62,6 +62,9 @@ var HtmlHighlightRules = function() {
merge : true,
regex : "<\\!--",
next : "comment"
}, {
token : "xml_pe",
regex : "<\\!.*?>"
}, {
token : "meta.tag",
regex : "<(?=\s*script\\b)",
@ -77,6 +80,9 @@ var HtmlHighlightRules = function() {
}, {
token : "text",
regex : "\\s+"
}, {
token : "constant.character.entity",
regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
}, {
token : "text",
regex : "[^<]+"

View file

@ -65,7 +65,7 @@ var JavaHighlightRules = function() {
token : "comment",
regex : "\\/\\/.*$"
},
new DocCommentHighlightRules().getStartRule("doc-start"),
DocCommentHighlightRules.getStartRule("doc-start"),
{
token : "comment", // multi line comment
merge : true,
@ -135,7 +135,7 @@ var JavaHighlightRules = function() {
};
this.embedRules(DocCommentHighlightRules, "doc-",
[ new DocCommentHighlightRules().getEndRule("start") ]);
[ DocCommentHighlightRules.getEndRule("start") ]);
};
oop.inherits(JavaHighlightRules, TextHighlightRules);

View file

@ -116,7 +116,7 @@ var JavaScriptHighlightRules = function() {
token : "comment",
regex : /\/\/.*$/
},
new DocCommentHighlightRules().getStartRule("doc-start"),
DocCommentHighlightRules.getStartRule("doc-start"),
{
token : "comment", // multi line comment
merge : true,
@ -124,11 +124,11 @@ var JavaScriptHighlightRules = function() {
next : "comment"
}, {
token : "string",
regex : "'",
regex : "'(?=.)",
next : "qstring"
}, {
token : "string",
regex : '"',
regex : '"(?=.)',
next : "qqstring"
}, {
token : "constant.numeric", // hex
@ -148,11 +148,10 @@ var JavaScriptHighlightRules = function() {
"text",
"storage.type",
"text",
"paren.lparen",
"variable.parameter",
"paren.rparen"
"paren.lparen"
],
regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
next: "function_arguments"
}, { // match stuff like: Sound.prototype.play = myfunc
token : [
"storage.type",
@ -164,7 +163,8 @@ var JavaScriptHighlightRules = function() {
"keyword.operator",
"text"
],
regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)"
regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)",
next: "function_arguments"
}, { // match stuff like: Sound.play = function() { }
token : [
"storage.type",
@ -175,11 +175,10 @@ var JavaScriptHighlightRules = function() {
"text",
"storage.type",
"text",
"paren.lparen",
"variable.parameter",
"paren.rparen"
"paren.lparen"
],
regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
next: "function_arguments"
}, { // match stuff like: play = function() { }
token : [
"entity.name.function",
@ -188,22 +187,20 @@ var JavaScriptHighlightRules = function() {
"text",
"storage.type",
"text",
"paren.lparen",
"variable.parameter",
"paren.rparen"
"paren.lparen"
],
regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()",
next: "function_arguments"
}, { // match regular function like: function myFunc(arg) { }
token : [
"storage.type",
"text",
"entity.name.function",
"text",
"paren.lparen",
"variable.parameter",
"paren.rparen"
"paren.lparen"
],
regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()(.*?)(\\))"
regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()",
next: "function_arguments"
}, { // match stuff like: foobar: function() { }
token : [
"entity.name.function",
@ -212,22 +209,20 @@ var JavaScriptHighlightRules = function() {
"text",
"storage.type",
"text",
"paren.lparen",
"variable.parameter",
"paren.rparen"
"paren.lparen"
],
regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()(.*?)(\\))"
regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()",
next: "function_arguments"
}, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })
token : [
"text",
"text",
"storage.type",
"text",
"paren.lparen",
"variable.parameter",
"paren.rparen"
"paren.lparen"
],
regex : "(:)(\\s*)(function)?(\\s*)(\\()([^)]*)(\\))"
regex : "(:)(\\s*)(function)(\\s*)(\\()",
next: "function_arguments"
}, {
token : "constant.language.boolean",
regex : /(?:true|false)\b/
@ -236,14 +231,14 @@ var JavaScriptHighlightRules = function() {
regex : "(?:" + kwBeforeRe + ")\\b",
next : "regex_allowed"
}, {
token : "support.function",
regex : /\b(?:s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
token : ["punctuation.operator", "support.function"],
regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/
}, {
token : "support.function.dom",
regex : /\b(?:s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
token : ["punctuation.operator", "support.function.dom"],
regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/
}, {
token : ["punctuation.operator", "support.constant"],
regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image))\b)/
regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/
}, {
token : ["storage.type", "punctuation.operator", "support.function.firebug"],
regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/
@ -297,6 +292,7 @@ var JavaScriptHighlightRules = function() {
// regular expressions are only allowed after certain tokens. This
// makes sure we don't mix up regexps with the divison operator
"regex_allowed": [
DocCommentHighlightRules.getStartRule("doc-start"),
{
token : "comment", // multi line comment
merge : true,
@ -324,10 +320,9 @@ var JavaScriptHighlightRules = function() {
"regex": [
{
token: "regexp.keyword.operator",
regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",
next: "regex"
regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
}, {
// flag
// flag
token: "string.regexp",
regex: "/\\w*",
next: "start",
@ -335,7 +330,6 @@ var JavaScriptHighlightRules = function() {
}, {
token: "string.regexp",
regex: "[^\\\\/\\[]+",
next: "regex",
merge: true
}, {
token: "string.regexp.charachterclass",
@ -351,8 +345,7 @@ var JavaScriptHighlightRules = function() {
"regex_character_class": [
{
token: "regexp.keyword.operator",
regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)",
next: "regex_character_class"
regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)"
}, {
token: "string.regexp.charachterclass",
regex: "]",
@ -361,7 +354,24 @@ var JavaScriptHighlightRules = function() {
}, {
token: "string.regexp.charachterclass",
regex: "[^\\\\\\]]+",
next: "regex_character_class",
merge: true
}, {
token: "empty",
regex: "",
next: "start"
}
],
"function_arguments": [
{
token: "variable.parameter",
regex: identifierRe,
}, {
token: "punctuation.operator",
regex: "[, ]+",
merge: true
}, {
token: "punctuation.operator",
regex: "$",
merge: true
}, {
token: "empty",
@ -399,11 +409,18 @@ var JavaScriptHighlightRules = function() {
regex : escapedRe
}, {
token : "string",
regex : '[^"\\\\]+'
regex : '[^"\\\\]+',
merge : true
}, {
token : "string",
regex : '"',
next : "start"
regex : "\\\\$",
next : "qqstring",
merge : true
}, {
token : "string",
regex : '"|$',
next : "start",
merge : true
}
],
"qstring" : [
@ -412,17 +429,24 @@ var JavaScriptHighlightRules = function() {
regex : escapedRe
}, {
token : "string",
regex : "[^'\\\\]+"
regex : "[^'\\\\]+",
merge : true
}, {
token : "string",
regex : "'",
next : "start"
regex : "\\\\$",
next : "qstring",
merge : true
}, {
token : "string",
regex : "'|$",
next : "start",
merge : true
}
]
};
this.embedRules(DocCommentHighlightRules, "doc-",
[ new DocCommentHighlightRules().getEndRule("start") ]);
[ DocCommentHighlightRules.getEndRule("start") ]);
};
oop.inherits(JavaScriptHighlightRules, TextHighlightRules);

View file

@ -46,9 +46,9 @@ var JavaScriptMode = require("./javascript").Mode;
var assert = require("../test/assertions");
module.exports = {
name: "JavaScript Tokenizer",
setUp : function() {
this.tokenizer = new JavaScriptMode().getTokenizer();
},
@ -71,12 +71,12 @@ module.exports = {
var tokens = this.tokenizer.getLineTokens(line, "start").tokens;
assert.equal(27, tokens.length);
assert.equal(23, tokens.length);
assert.equal("support.function", tokens[2].type); // charCodeAt
assert.equal("support.function.dom", tokens[10].type); // getElementById
assert.equal("support.function.firebug", tokens[20].type); // log
assert.equal("support.function.firebug", tokens[18].type); // log
},
"test: tokenize doc comment" : function() {
var line = "abc /** de */ fg";
@ -135,11 +135,11 @@ module.exports = {
var tokens = this.tokenizer.getLineTokens("a=/b/g", "start").tokens;
assert.equal(3, tokens.length);
assert.equal("string.regexp", tokens[2].type);
var tokens = this.tokenizer.getLineTokens("a+/b/g", "start").tokens;
assert.equal(3, tokens.length);
assert.equal("string.regexp", tokens[2].type);
var tokens = this.tokenizer.getLineTokens("a = 1 + /2 + 1/b", "start").tokens;
assert.equal(9, tokens.length);
assert.equal("string.regexp", tokens[8].type);
@ -148,17 +148,17 @@ module.exports = {
assert.equal(7, tokens.length);
assert.equal("string.regexp", tokens[2].type);
assert.equal("string.regexp", tokens[6].type);
var tokens = this.tokenizer.getLineTokens("case /a/.test(c)", "start").tokens;
assert.equal(8, tokens.length);
assert.equal("string.regexp", tokens[2].type);
},
"test tokenize multi-line comment containing a single line comment" : function() {
var tokens = this.tokenizer.getLineTokens("/* foo // bar */", "start").tokens;
assert.equal(1, tokens.length);
assert.equal("comment", tokens[0].type);
var tokens = this.tokenizer.getLineTokens("/* foo // bar */", "regex_allowed").tokens;
assert.equal(1, tokens.length);
assert.equal("comment", tokens[0].type);
@ -168,7 +168,7 @@ module.exports = {
var tokens = this.tokenizer.getLineTokens("füße", "start").tokens;
assert.equal(1, tokens.length);
},
"test // is not a regexp": function() {
var tokens = this.tokenizer.getLineTokens("{ // 123", "start").tokens;
assert.equal(3, tokens.length);
@ -176,19 +176,45 @@ module.exports = {
assert.equal("text", tokens[1].type);
assert.equal("comment", tokens[2].type);
},
"test skipping escaped chars": function() {
var line = "console.log('Meh\\nNeh');"
var tokens = this.tokenizer.getLineTokens(line, "start").tokens;
assert.equal(11, tokens.length);
assert.equal("constant.language.escape", tokens[6].type);
assert.equal(9, tokens.length);
assert.equal("constant.language.escape", tokens[5].type);
line = "console.log('\\u1232Feh');";
tokens = this.tokenizer.getLineTokens(line, "start").tokens;
assert.equal(10, tokens.length);
assert.equal(9, tokens.length);
assert.equal("constant.language.escape", tokens[5].type);
},
"test multiline strings": function() {
var line = "console.log('Meh\\"
var data = this.tokenizer.getLineTokens(line, "start")
assert.equal(5, data.tokens.length);
assert.equal(data.state, "qstring");
line = "console.log('Meh\\ "
data = this.tokenizer.getLineTokens(line, "start")
assert.equal(6, data.tokens.length);
assert.equal(data.state, "start");
line = 'console.log("\\'
data = this.tokenizer.getLineTokens(line, "start")
assert.equal(5, data.tokens.length);
assert.equal(data.state, "qqstring");
line = 'a="'
data = this.tokenizer.getLineTokens(line, "start")
assert.equal(3, data.tokens.length);
assert.equal(data.state, "start");
}
};

87
lib/ace/mode/less.js Normal file
View file

@ -0,0 +1,87 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Fabian Jakobs <fabian AT ajax DOT org>
* John Roepke <john AT justjohn DOT us>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var Tokenizer = require("../tokenizer").Tokenizer;
var LessHighlightRules = require("./less_highlight_rules").LessHighlightRules;
var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
var CStyleFoldMode = require("./folding/cstyle").FoldMode;
var Mode = function() {
this.$tokenizer = new Tokenizer(new LessHighlightRules().getRules(), "i");
this.$outdent = new MatchingBraceOutdent();
this.foldingRules = new CStyleFoldMode();
};
oop.inherits(Mode, TextMode);
(function() {
this.getNextLineIndent = function(state, line, tab) {
var indent = this.$getIndent(line);
// ignore braces in comments
var tokens = this.$tokenizer.getLineTokens(line, state).tokens;
if (tokens.length && tokens[tokens.length-1].type == "comment") {
return indent;
}
var match = line.match(/^.*\{\s*$/);
if (match) {
indent += tab;
}
return indent;
};
this.checkOutdent = function(state, line, input) {
return this.$outdent.checkOutdent(line, input);
};
this.autoOutdent = function(state, doc, row) {
this.$outdent.autoOutdent(doc, row);
};
}).call(Mode.prototype);
exports.Mode = Mode;
});

View file

@ -0,0 +1,279 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Fabian Jakobs <fabian AT ajax DOT org>
* John Roepke <john AT justjohn DOT us>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var lang = require("../lib/lang");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var LessHighlightRules = function() {
var properties = lang.arrayToMap( (function () {
var browserPrefix = ("-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-").split("|");
var prefixProperties = ("appearance|background-clip|background-inline-policy|background-origin|" +
"background-size|binding|border-bottom-colors|border-left-colors|" +
"border-right-colors|border-top-colors|border-end|border-end-color|" +
"border-end-style|border-end-width|border-image|border-start|" +
"border-start-color|border-start-style|border-start-width|box-align|" +
"box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|" +
"box-pack|box-sizing|column-count|column-gap|column-width|column-rule|" +
"column-rule-width|column-rule-style|column-rule-color|float-edge|" +
"font-feature-settings|font-language-override|force-broken-image-icon|" +
"image-region|margin-end|margin-start|opacity|outline|outline-color|" +
"outline-offset|outline-radius|outline-radius-bottomleft|" +
"outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|" +
"outline-style|outline-width|padding-end|padding-start|stack-sizing|" +
"tab-size|text-blink|text-decoration-color|text-decoration-line|" +
"text-decoration-style|transform|transform-origin|transition|" +
"transition-delay|transition-duration|transition-property|" +
"transition-timing-function|user-focus|user-input|user-modify|user-select|" +
"window-shadow|border-radius").split("|");
var properties = ("azimuth|background-attachment|background-color|background-image|" +
"background-position|background-repeat|background|border-bottom-color|" +
"border-bottom-style|border-bottom-width|border-bottom|border-collapse|" +
"border-color|border-left-color|border-left-style|border-left-width|" +
"border-left|border-right-color|border-right-style|border-right-width|" +
"border-right|border-spacing|border-style|border-top-color|" +
"border-top-style|border-top-width|border-top|border-width|border|" +
"bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|" +
"counter-reset|cue-after|cue-before|cue|cursor|direction|display|" +
"elevation|empty-cells|float|font-family|font-size-adjust|font-size|" +
"font-stretch|font-style|font-variant|font-weight|font|height|left|" +
"letter-spacing|line-height|list-style-image|list-style-position|" +
"list-style-type|list-style|margin-bottom|margin-left|margin-right|" +
"margin-top|marker-offset|margin|marks|max-height|max-width|min-height|" +
"min-width|opacity|orphans|outline-color|" +
"outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|" +
"padding-left|padding-right|padding-top|padding|page-break-after|" +
"page-break-before|page-break-inside|page|pause-after|pause-before|" +
"pause|pitch-range|pitch|play-during|position|quotes|richness|right|" +
"size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|" +
"stress|table-layout|text-align|text-decoration|text-indent|" +
"text-shadow|text-transform|top|unicode-bidi|vertical-align|" +
"visibility|voice-family|volume|white-space|widows|width|word-spacing|" +
"z-index").split("|");
//The return array
var ret = [];
//All prefixProperties will get the browserPrefix in
//the begning by join the prefixProperties array with the value of browserPrefix
for (var i=0, ln=browserPrefix.length; i<ln; i++) {
Array.prototype.push.apply(
ret,
(( browserPrefix[i] + prefixProperties.join("|" + browserPrefix[i]) ).split("|"))
);
}
//Add also prefixProperties and properties without any browser prefix
Array.prototype.push.apply(ret, prefixProperties);
Array.prototype.push.apply(ret, properties);
return ret;
})() );
var functions = lang.arrayToMap(
("hsl|hsla|rgb|rgba|url|attr|counter|counters|lighten|darken|saturate|" +
"desaturate|fadein|fadeout|fade|spin|mix|hue|saturation|lightness|" +
"alpha|round|ceil|floor|percentage|color|iscolor|isnumber|isstring|" +
"iskeyword|isurl|ispixel|ispercentage|isem").split("|")
);
var constants = lang.arrayToMap(
("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|" +
"block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|" +
"char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|" +
"decimal-leading-zero|decimal|default|disabled|disc|" +
"distribute-all-lines|distribute-letter|distribute-space|" +
"distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|" +
"hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|" +
"ideograph-alpha|ideograph-numeric|ideograph-parenthesis|" +
"ideograph-space|inactive|inherit|inline-block|inline|inset|inside|" +
"inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|" +
"keep-all|left|lighter|line-edge|line-through|line|list-item|loose|" +
"lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|" +
"medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|" +
"nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|" +
"overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|" +
"ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|" +
"solid|square|static|strict|super|sw-resize|table-footer-group|" +
"table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|" +
"transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|" +
"vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|" +
"zero").split("|")
);
var colors = lang.arrayToMap(
("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|" +
"purple|red|silver|teal|white|yellow").split("|")
);
var keywords = lang.arrayToMap(
("@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|" +
"@while|@else|@font-face|@-webkit-keyframes|if|and|!default|module|" +
"def|end|declare|when|not|and").split("|")
);
var tags = lang.arrayToMap(
("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|" +
"big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|" +
"command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|" +
"figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|" +
"header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|" +
"link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|" +
"option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|" +
"small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|" +
"textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp").split("|")
);
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
var numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
this.$rules = {
"start" : [
{
token : "comment",
regex : "\\/\\/.*$"
},
{
token : "comment", // multi line comment
merge : true,
regex : "\\/\\*",
next : "comment"
}, {
token : "string", // single line
regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
}, {
token : "string", // single line
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
}, {
token : "constant.numeric",
regex : numRe + "(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"
}, {
token : "constant.numeric", // hex6 color
regex : "#[a-f0-9]{6}"
}, {
token : "constant.numeric", // hex3 color
regex : "#[a-f0-9]{3}"
}, {
token : "constant.numeric",
regex : numRe
}, {
token : function(value) {
if (keywords.hasOwnProperty(value))
return "keyword";
else
return "variable";
},
regex : "@[a-z0-9_\\-@]*\\b"
}, {
token : function(value) {
if (properties.hasOwnProperty(value.toLowerCase()))
return "support.type";
else if (keywords.hasOwnProperty(value))
return "keyword";
else if (constants.hasOwnProperty(value))
return "constant.language";
else if (functions.hasOwnProperty(value))
return "support.function";
else if (colors.hasOwnProperty(value.toLowerCase()))
return "support.constant.color";
else if (tags.hasOwnProperty(value.toLowerCase()))
return "variable.language";
else
return "text";
},
regex : "\\-?[@a-z_][@a-z0-9_\\-]*"
}, {
token: "variable.language",
regex: "#[a-z0-9-_]+"
}, {
token: "variable.language",
regex: "\\.[a-z0-9-_]+"
}, {
token: "variable.language",
regex: ":[a-z0-9-_]+"
}, {
token: "constant",
regex: "[a-z0-9-_]+"
}, {
token : "keyword.operator",
regex : "<|>|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"
}, {
token : "paren.lparen",
regex : "[[({]"
}, {
token : "paren.rparen",
regex : "[\\])}]"
}, {
token : "text",
regex : "\\s+"
}
],
"comment" : [
{
token : "comment", // closing comment
regex : ".*?\\*\\/",
next : "start"
}, {
token : "comment", // comment spanning whole line
merge : true,
regex : ".+"
}
]
};
};
oop.inherits(LessHighlightRules, TextHighlightRules);
exports.LessHighlightRules = LessHighlightRules;
});

View file

@ -442,7 +442,7 @@ var PgsqlHighlightRules = function() {
token : "comment",
regex : "--.*$"
},
new DocCommentHighlightRules().getStartRule("doc-start"),
DocCommentHighlightRules.getStartRule("doc-start"),
{
token : "comment", // multi-line comment
merge : true,
@ -571,7 +571,7 @@ var PgsqlHighlightRules = function() {
]
};
this.embedRules(DocCommentHighlightRules, "doc-", [ new DocCommentHighlightRules().getEndRule("start") ]);
this.embedRules(DocCommentHighlightRules, "doc-", [ DocCommentHighlightRules.getEndRule("start") ]);
this.embedRules(PerlHighlightRules, "perl-", [{token : "string", regex : "\\$perl\\$", next : "statement"}]);
this.embedRules(PythonHighlightRules, "python-", [{token : "string", regex : "\\$python\\$", next : "statement"}]);
};

View file

@ -45,7 +45,7 @@ var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocComme
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var PhpHighlightRules = function() {
var docComment = new DocCommentHighlightRules();
var docComment = DocCommentHighlightRules;
// http://php.net/quickref.php
var builtinFunctions = lang.arrayToMap(
('abs|acos|acosh|addcslashes|addslashes|aggregate|aggregate_info|aggregate_methods|aggregate_methods_by_list|aggregate_methods_by_regexp|' +
@ -1150,7 +1150,7 @@ var PhpHighlightRules = function() {
};
this.embedRules(DocCommentHighlightRules, "doc-",
[ new DocCommentHighlightRules().getEndRule("start") ]);
[ DocCommentHighlightRules.getEndRule("start") ]);
};
oop.inherits(PhpHighlightRules, TextHighlightRules);

View file

@ -65,7 +65,7 @@ var scadHighlightRules = function() {
token : "comment",
regex : "\\/\\/.*$"
},
new DocCommentHighlightRules().getStartRule("start"),
DocCommentHighlightRules.getStartRule("start"),
{
token : "comment", // multi line comment
merge : true,
@ -159,7 +159,7 @@ var scadHighlightRules = function() {
};
this.embedRules(DocCommentHighlightRules, "doc-",
[ new DocCommentHighlightRules().getEndRule("start") ]);
[ DocCommentHighlightRules.getEndRule("start") ]);
};
oop.inherits(scadHighlightRules, TextHighlightRules);

View file

@ -65,7 +65,7 @@ var ScalaHighlightRules = function() {
token : "comment",
regex : "\\/\\/.*$"
},
new DocCommentHighlightRules().getStartRule("doc-start"),
DocCommentHighlightRules.getStartRule("doc-start"),
{
token : "comment", // multi line comment
merge : true,
@ -135,7 +135,7 @@ var ScalaHighlightRules = function() {
};
this.embedRules(DocCommentHighlightRules, "doc-",
[ new DocCommentHighlightRules().getEndRule("start") ]);
[ DocCommentHighlightRules.getEndRule("start") ]);
};
oop.inherits(ScalaHighlightRules, TextHighlightRules);

View file

@ -65,8 +65,6 @@ var TextHighlightRules = function() {
var rule = state[i];
if (rule.next) {
rule.next = prefix + rule.next;
} else {
rule.next = prefix + key;
}
}
this.$rules[prefix + key] = state;

View file

@ -59,6 +59,9 @@ var XmlHighlightRules = function() {
merge : true,
regex : "<\\!--",
next : "comment"
}, {
token : "xml_pe",
regex : "<\\!.*?>"
}, {
token : "meta.tag", // opening tag
regex : "<\\/?",
@ -66,6 +69,9 @@ var XmlHighlightRules = function() {
}, {
token : "text",
regex : "\\s+"
}, {
token : "constant.character.entity",
regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
}, {
token : "text",
regex : "[^<]+"

View file

@ -112,7 +112,7 @@ exports.tag = function(states, name, nextState) {
}
},
merge : true,
regex : "[-_a-zA-Z0-9:!]+",
regex : "[-_a-zA-Z0-9:]+",
next : name + "_embed_attribute_list"
}, {
token: "empty",

View file

@ -134,7 +134,7 @@ function DefaultHandlers(editor) {
if (!editor.$mouseHandler.$clickSelection) {
if (!dragCursor) {
editor.moveCursorToPosition(pos);
editor.selection.clearSelection(pos.row, pos.column);
editor.selection.clearSelection();
}
}
@ -169,7 +169,6 @@ function DefaultHandlers(editor) {
if (distance > DRAG_OFFSET) {
state = STATE_SELECT;
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
onStartSelect(cursor);
}
else if ((time - mousedownTime) > editor.getDragDelay()) {
@ -196,7 +195,7 @@ function DefaultHandlers(editor) {
else {
if (!_self.$clickSelection) {
editor.moveCursorToPosition(pos);
editor.selection.clearSelection(pos.row, pos.column);
editor.selection.clearSelection();
}
}
state = STATE_SELECT;
@ -205,7 +204,6 @@ function DefaultHandlers(editor) {
var onUpdateSelectionInterval = function() {
var anchor;
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
if (_self.$clickSelection) {
if (_self.$clickSelection.contains(cursor.row, cursor.column)) {
@ -231,8 +229,6 @@ function DefaultHandlers(editor) {
var onDragSelectionInterval = function() {
dragCursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
dragCursor.row = Math.max(0, Math.min(dragCursor.row, editor.session.getLength() - 1));
editor.moveCursorToPosition(dragCursor);
};

View file

@ -45,7 +45,7 @@ function FoldHandler(editor) {
var position = e.getDocumentPosition();
var session = editor.session;
// If the user dclicked on a fold, then expand it.
// If the user clicked on a fold, then expand it.
var fold = session.getFoldAt(position.row, position.column, 1);
if (fold) {
if (e.getAccelKey())

View file

@ -90,7 +90,6 @@ var MouseEvent = exports.MouseEvent = function(domEvent, editor) {
var pageX = event.getDocumentX(this.domEvent);
var pageY = event.getDocumentY(this.domEvent);
this.$pos = this.editor.renderer.screenToTextCoordinates(pageX, pageY);
this.$pos.row = Math.max(0, Math.min(this.$pos.row, this.editor.session.getLength()-1));
return this.$pos;
};

View file

@ -0,0 +1,167 @@
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Harutyun Amirjanyan <amirjanyan AT gmail DOT com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
var event = require("../lib/event");
// mouse
function isSamePoint(p1, p2) {
return p1.row == p2.row && p1.column == p2.column;
}
function onMouseDown(e) {
var ev = e.domEvent;
var alt = ev.altKey;
var shift = ev.shiftKey;
var ctrl = e.getAccelKey();
var button = e.getButton();
if (!ctrl && !alt) {
if (e.editor.inMultiSelectMode) {
if (button == 0) {
e.editor.exitMultiSelectMode();
} else if (button == 2) {
var editor = e.editor;
var selectionEmpty = editor.selection.isEmpty();
editor.textInput.onContextMenu({x: e.clientX, y: e.clientY}, selectionEmpty);
event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose);
e.stop();
}
}
return;
}
var editor = e.editor;
var selection = editor.selection;
var isMultiSelect = editor.inMultiSelectMode;
var pos = e.getDocumentPosition();
var cursor = selection.getCursor();
var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));
var mouseX = e.pageX, mouseY = e.pageY;
var onMouseSelection = function(e) {
mouseX = event.getDocumentX(e);
mouseY = event.getDocumentY(e);
};
var blockSelect = function() {
var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column);
if (isSamePoint(screenCursor, newCursor)
&& isSamePoint(cursor, selection.selectionLead))
return;
screenCursor = newCursor;
editor.selection.moveCursorToPosition(cursor);
editor.selection.clearSelection();
editor.renderer.scrollCursorIntoView();
editor.removeSelectionMarkers(rectSel);
rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);
rectSel.forEach(editor.addSelectionMarker, editor);
editor.updateSelectionMarkers();
};
var session = editor.session;
var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);
var screenCursor = screenAnchor;
if (ctrl && !shift && !alt && button == 0) {
if (!isMultiSelect && inSelection)
return; // dragging
if (!isMultiSelect) {
var range = selection.toOrientedRange();
editor.addSelectionMarker(range);
}
var oldRange = selection.rangeList.rangeAtPoint(pos);
event.capture(editor.container, function(){}, function() {
var tmpSel = selection.toOrientedRange();
if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor))
selection.substractPoint(tmpSel.cursor);
else {
if (range) {
editor.removeSelectionMarker(range);
selection.addRange(range);
}
selection.addRange(tmpSel);
}
});
} else if (!shift && alt && button == 0) {
e.stop();
if (isMultiSelect && !ctrl)
selection.toSingleRange();
else if (!isMultiSelect && ctrl)
selection.addRange();
selection.moveCursorToPosition(pos);
selection.clearSelection();
var rectSel = [];
var onMouseSelectionEnd = function(e) {
clearInterval(timerId);
editor.removeSelectionMarkers(rectSel);
for (var i = 0; i < rectSel.length; i++)
selection.addRange(rectSel[i]);
};
var onSelectionInterval = blockSelect;
event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
var timerId = setInterval(function() {onSelectionInterval();}, 20);
return e.preventDefault();
}
}
exports.onMouseDown = onMouseDown;
});

707
lib/ace/multi_select.js Normal file
View file

@ -0,0 +1,707 @@
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Harutyun Amirjanyan <amirjanyan AT gmail DOT com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
var RangeList = require("./range_list").RangeList;
var Range = require("./range").Range;
var Selection = require("./selection").Selection;
var onMouseDown = require("./mouse/multi_select_handler").onMouseDown;
exports.commands = require("./commands/multi_select_commands");
// Todo: session.find or editor.findVolatile that returns range
var Search = require("./search").Search;
var search = new Search();
function find(session, needle, dir) {
search.$options.wrap = true;
search.$options.needle = needle;
search.$options.backwards = dir == -1;
return search.find(session);
}
// extend EditSession
var EditSession = require("./edit_session").EditSession;
(function() {
this.getSelectionMarkers = function() {
return this.$selectionMarkers;
};
}).call(EditSession.prototype);
// extend Selection
(function() {
// list of ranges in reverse addition order
this.ranges = null;
// automatically sorted list of ranges
this.rangeList = null;
/**
* Selection.addRange(Range) -> Void
*
* adds a range to selection entering multiselect mode if necessary
**/
this.addRange = function(range, $blockChangeEvents) {
if (!range)
return;
if (!this.inMultiSelectMode && this.rangeCount == 0) {
var oldRange = this.toOrientedRange();
if (range.intersects(oldRange))
return $blockChangeEvents || this.fromOrientedRange(range);
this.rangeList.add(oldRange);
this.$onAddRange(oldRange);
}
if (!range.cursor)
range.cursor = range.end;
var removed = this.rangeList.add(range);
this.$onAddRange(range);
if (removed.length)
this.$onRemoveRange(removed);
if (this.rangeCount > 1 && !this.inMultiSelectMode) {
this._emit("multiSelect");
this.inMultiSelectMode = true;
this.session.$undoSelect = false;
this.rangeList.attach(this.session);
}
return $blockChangeEvents || this.fromOrientedRange(range);
};
this.toSingleRange = function(range) {
range = range || this.ranges[0];
var removed = this.rangeList.removeAll();
if (removed.length)
this.$onRemoveRange(removed);
range && this.fromOrientedRange(range);
};
/**
* Selection.addRange(pos) -> Range
* pos: {row, column}
*
* removes range containing pos (if exists)
**/
this.substractPoint = function(pos) {
var removed = this.rangeList.substractPoint(pos);
if (removed) {
this.$onRemoveRange(removed);
return removed[0];
}
};
/**
* Selection.mergeOverlappingRanges() -> Void
*
* merges overlapping ranges ensuring consistency after changes
**/
this.mergeOverlappingRanges = function() {
var removed = this.rangeList.merge();
if (removed.length)
this.$onRemoveRange(removed);
else if(this.ranges[0])
this.fromOrientedRange(this.ranges[0]);
};
this.$onAddRange = function(range) {
this.rangeCount = this.rangeList.ranges.length;
this.ranges.unshift(range);
this._emit("addRange", {range: range});
};
this.$onRemoveRange = function(removed) {
this.rangeCount = this.rangeList.ranges.length;
if (this.rangeCount == 1 && this.inMultiSelectMode) {
var lastRange = this.rangeList.ranges.pop();
removed.push(lastRange);
this.rangeCount = 0;
}
for (var i = removed.length; i--; ) {
var index = this.ranges.indexOf(removed[i]);
this.ranges.splice(index, 1);
}
this._emit("removeRange", {ranges: removed});
if (this.rangeCount == 0 && this.inMultiSelectMode) {
this.inMultiSelectMode = false;
this._emit("singleSelect");
this.session.$undoSelect = true;
this.rangeList.detach(this.session);
}
lastRange = lastRange || this.ranges[0];
if (lastRange && !lastRange.isEqual(this.getRange()))
this.fromOrientedRange(lastRange);
};
// adds multicursor support to selection
this.$initRangeList = function() {
if (this.rangeList)
return;
this.rangeList = new RangeList();
this.ranges = [];
this.rangeCount = 0;
};
this.getAllRanges = function() {
return this.rangeList.ranges.concat();
};
this.splitIntoLines = function () {
if (this.rangeCount > 1) {
var ranges = this.rangeList.ranges;
var lastRange = ranges[ranges.length - 1];
var range = Range.fromPoints(ranges[0].start, lastRange.end);
this.toSingleRange();
this.setSelectionRange(range, lastRange.cursor == lastRange.start);
} else {
var cursor = this.session.documentToScreenPosition(this.selectionLead);
var anchor = this.session.documentToScreenPosition(this.selectionAnchor);
var rectSel = this.rectangularRangeBlock(cursor, anchor);
rectSel.forEach(this.addRange, this);
}
};
/**
* Selection.rectangularRangeBlock(screenCursor, screenAnchor, includeEmptyLines) -> [Range]
* gets list of ranges composing rectangular block on the screen
* @includeEmptyLines if true includes ranges inside the block which
* are empty becuase of the clipping
*/
this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) {
var rectSel = [];
var xBackwards = screenCursor.column < screenAnchor.column;
if (xBackwards) {
var startColumn = screenCursor.column;
var endColumn = screenAnchor.column;
} else {
var startColumn = screenAnchor.column;
var endColumn = screenCursor.column;
}
var yBackwards = screenCursor.row < screenAnchor.row;
if (yBackwards) {
var startRow = screenCursor.row;
var endRow = screenAnchor.row;
} else {
var startRow = screenAnchor.row;
var endRow = screenCursor.row;
}
if (startColumn < 0)
startColumn = 0;
if (startRow < 0)
startRow = 0;
if (startRow == endRow)
includeEmptyLines = true;
for (var row = startRow; row <= endRow; row++) {
var range = Range.fromPoints(
this.session.screenToDocumentPosition(row, startColumn),
this.session.screenToDocumentPosition(row, endColumn)
);
if (range.isEmpty()) {
if (docEnd && isSamePoint(range.end, docEnd))
break;
var docEnd = range.end;
}
range.cursor = xBackwards ? range.start : range.end;
rectSel.push(range);
}
if (yBackwards)
rectSel.reverse();
if (!includeEmptyLines) {
var end = rectSel.length - 1;
while (rectSel[end].isEmpty() && end > 0)
end--;
if (end > 0) {
var start = 0;
while (rectSel[start].isEmpty())
start++;
}
for (var i = end; i >= start; i--) {
if (rectSel[i].isEmpty())
rectSel.splice(i, 1);
}
}
return rectSel;
};
}).call(Selection.prototype);
// extend Editor
var Editor = require("./editor").Editor;
(function() {
/**
* Editor.updateSelectionMarkers() -> Void
*
* updates cursor and marker layers
**/
this.updateSelectionMarkers = function() {
this.renderer.updateCursor();
this.renderer.updateBackMarkers();
};
/**
* Editor.addSelectionMarker(orientedRange) -> Range
* - orientedRange: range with cursor
*
* adds selection and cursor
**/
this.addSelectionMarker = function(orientedRange) {
if (!orientedRange.cursor)
orientedRange.cursor = orientedRange.end;
var style = this.getSelectionStyle();
orientedRange.marker = this.session.addMarker(orientedRange, "ace_selection", style);
this.session.$selectionMarkers.push(orientedRange);
this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
return orientedRange;
};
/**
* Editor.removeSelectionMarker(range) -> Void
* - range: selection range added with addSelectionMarker
*
* removes selection marker
**/
this.removeSelectionMarker = function(range) {
if (!range.marker)
return;
this.session.removeMarker(range.marker);
var index = this.session.$selectionMarkers.indexOf(range);
if (index != -1)
this.session.$selectionMarkers.splice(index, 1);
this.session.selectionMarkerCount = this.session.$selectionMarkers.length;
};
this.removeSelectionMarkers = function(ranges) {
var markerList = this.session.$selectionMarkers;
for (var i = ranges.length; i--; ) {
var range = ranges[i];
if (!range.marker)
continue;
this.session.removeMarker(range.marker);
var index = markerList.indexOf(range);
if (index != -1)
markerList.splice(index, 1);
}
this.session.selectionMarkerCount = markerList.length;
};
this.$onAddRange = function(e) {
this.addSelectionMarker(e.range);
this.renderer.updateCursor();
this.renderer.updateBackMarkers();
};
this.$onRemoveRange = function(e) {
this.removeSelectionMarkers(e.ranges);
this.renderer.updateCursor();
this.renderer.updateBackMarkers();
};
this.$onMultiSelect = function(e) {
if (this.inMultiSelectMode)
return;
this.inMultiSelectMode = true;
this.setStyle("multiselect");
this.keyBinding.addKeyboardHandler(exports.commands.keyboardHandler);
this.commands.on("exec", this.$onMultiSelectExec);
this.renderer.updateCursor();
this.renderer.updateBackMarkers();
};
this.$onSingleSelect = function(e) {
if (this.session.multiSelect.inVirtualMode)
return;
this.inMultiSelectMode = false;
this.unsetStyle("multiselect");
this.keyBinding.removeKeyboardHandler(exports.commands.keyboardHandler);
this.commands.removeEventListener("exec", this.$onMultiSelectExec);
this.renderer.updateCursor();
this.renderer.updateBackMarkers();
};
this.$onMultiSelectExec = function(e) {
var command = e.command;
var editor = e.editor;
if (!command.multiSelectAction) {
command.exec(editor, e.args || {});
editor.multiSelect.addRange(editor.multiSelect.toOrientedRange());
editor.multiSelect.mergeOverlappingRanges();
} else if (command.multiSelectAction == "forEach") {
editor.forEachSelection(command, e.args);
} else if (command.multiSelectAction == "single") {
editor.exitMultiSelectMode();
command.exec(editor, e.args || {});
} else {
command.multiSelectAction(editor, e.args || {});
}
e.preventDefault();
};
/**
* Editor.forEachSelection(cmd, args) -> Void
* - cmd: command to execute
* - args: arguments to the command
*
* executes command for each selection range
**/
this.forEachSelection = function(cmd, args) {
if (this.inVirtualSelectionMode)
return;
var session = this.session;
var selection = this.selection;
var rangeList = selection.rangeList;
var reg = selection._eventRegistry;
selection._eventRegistry = {};
var tmpSel = new Selection(session);
this.inVirtualSelectionMode = true;
for (var i = rangeList.ranges.length; i--;) {
tmpSel.fromOrientedRange(rangeList.ranges[i]);
this.selection = session.selection = tmpSel;
cmd.exec(this, args || {});
tmpSel.toOrientedRange(rangeList.ranges[i]);
}
tmpSel.detach();
this.selection = session.selection = selection;
this.inVirtualSelectionMode = false;
selection._eventRegistry = reg;
selection.mergeOverlappingRanges();
this.onCursorChange();
this.onSelectionChange();
};
/**
* Editor.exitMultiSelectMode() -> Void
*
* removes all selections except the last added one.
**/
this.exitMultiSelectMode = function() {
if (this.inVirtualSelectionMode)
return;
this.multiSelect.toSingleRange();
};
this.getCopyText = function() {
var text = "";
if (this.inMultiSelectMode) {
var ranges = this.multiSelect.rangeList.ranges;
text = [];
for (var i = 0; i < ranges.length; i++) {
text.push(this.session.getTextRange(ranges[i]));
}
text = text.join(this.session.getDocument().getNewLineCharacter());
} else if (!this.selection.isEmpty()) {
text = this.session.getTextRange(this.getSelectionRange());
}
return text;
};
/**
* Editor.findAll(dir, options) -> Number
* - needle: text to find
* - options: search options
* - additive: keeps
*
* finds and selects all the occurencies of needle
* returns number of found ranges
**/
this.findAll = function(needle, options, additive) {
options = options || {};
options.needle = needle || options.needle;
this.$search.set(options);
var ranges = this.$search.findAll(this.session);
if (!ranges.length)
return 0;
this.$blockScrolling += 1;
var selection = this.multiSelect;
if (!additive)
selection.toSingleRange(ranges[0]);
for (var i = ranges.length; i--; )
selection.addRange(ranges[i], true);
this.$blockScrolling -= 1;
return ranges.length;
};
// commands
/**
* Editor.selectMoreLines(dir, skip) -> Void
* - dir: -1 up, 1 down
* - skip: remove active selection range if true
*
* adds cursor above or bellow active cursor
**/
this.selectMoreLines = function(dir, skip) {
var range = this.selection.toOrientedRange();
var isBackwards = range.cursor == range.end;
var screenLead = this.session.documentToScreenPosition(range.cursor);
if (this.selection.$desiredColumn)
screenLead.column = this.selection.$desiredColumn;
var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column);
if (!range.isEmpty()) {
var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start);
var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column);
} else {
var anchor = lead;
}
if (isBackwards) {
var newRange = Range.fromPoints(lead, anchor);
newRange.cursor = newRange.start;
} else {
var newRange = Range.fromPoints(anchor, lead);
newRange.cursor = newRange.end;
}
newRange.desiredColumn = screenLead.column;
if (!this.selection.inMultiSelectMode) {
this.selection.addRange(range);
} else {
if (skip)
var toRemove = range.cursor;
}
this.selection.addRange(newRange);
if (toRemove)
this.selection.substractPoint(toRemove);
};
/**
* Editor.transposeSelections(dir) -> Void
* - dir: direction to rotate selections
*
* contents
* empty ranges are expanded to word
**/
this.transposeSelections = function(dir) {
var session = this.session;
var sel = session.multiSelect;
var all = sel.ranges;
for (var i = all.length; i--; ) {
var range = all[i];
if (range.isEmpty()) {
var tmp = session.getWordRange(range.start.row, range.start.column);
range.start.row = tmp.start.row;
range.start.column = tmp.start.column;
range.end.row = tmp.end.row;
range.end.column = tmp.end.column;
}
}
sel.mergeOverlappingRanges();
var words = [];
for (var i = all.length; i--; ) {
var range = all[i];
words.unshift(session.getTextRange(range));
}
if (dir < 0)
words.unshift(words.pop());
else
words.push(words.shift());
for (var i = all.length; i--; ) {
var range = all[i];
var tmp = range.clone();
session.replace(range, words[i]);
range.start.row = tmp.start.row;
range.start.column = tmp.start.column;
}
}
/**
* Editor.selectMore(dir, skip) -> Void
* - dir: 1 next, -1 previous
* - skip: remove active selection range if true
*
* finds next occurence of text in active selection
* and adds it to the selections
**/
this.selectMore = function (dir, skip) {
var session = this.session;
var sel = session.multiSelect;
var range = sel.toOrientedRange();
if (range.isEmpty()) {
var range = session.getWordRange(range.start.row, range.start.column);
range.cursor = range.end;
this.multiSelect.addRange(range);
}
var needle = session.getTextRange(range);
var newRange = find(session, needle, dir);
if (newRange) {
newRange.cursor = dir == -1 ? newRange.start : newRange.end;
this.multiSelect.addRange(newRange);
}
if (skip)
this.multiSelect.substractPoint(range.cursor);
};
}).call(Editor.prototype);
function isSamePoint(p1, p2) {
return p1.row == p2.row && p1.column == p2.column;
}
// patch
// adds multicursor support to a session
exports.onSessionChange = function(e) {
var session = e.session;
if (!session.multiSelect) {
session.$selectionMarkers = [];
session.selection.$initRangeList();
session.multiSelect = session.selection;
}
this.multiSelect = session.multiSelect;
var oldSession = e.oldSession;
if (oldSession) {
// todo use events
if (oldSession.multiSelect && oldSession.multiSelect.editor == this)
oldSession.multiSelect.editor = null;
session.multiSelect.removeEventListener("addRange", this.$onAddRange);
session.multiSelect.removeEventListener("removeRange", this.$onRemoveRange);
session.multiSelect.removeEventListener("multiSelect", this.$onMultiSelect);
session.multiSelect.removeEventListener("singleSelect", this.$onSingleSelect);
}
session.multiSelect.on("addRange", this.$onAddRange);
session.multiSelect.on("removeRange", this.$onRemoveRange);
session.multiSelect.on("multiSelect", this.$onMultiSelect);
session.multiSelect.on("singleSelect", this.$onSingleSelect);
// this.$onSelectionChange = this.onSelectionChange.bind(this);
if (this.inMultiSelectMode != session.selection.inMultiSelectMode) {
if (session.selection.inMultiSelectMode)
this.$onMultiSelect();
else
this.$onSingleSelect();
}
};
/**
* MultiSelect(editor) -> Void
*
* adds multiple selection support to the editor
* (note: should be called only once for each editor instance)
**/
function MultiSelect(editor) {
editor.$onAddRange = editor.$onAddRange.bind(editor);
editor.$onRemoveRange = editor.$onRemoveRange.bind(editor);
editor.$onMultiSelect = editor.$onMultiSelect.bind(editor);
editor.$onSingleSelect = editor.$onSingleSelect.bind(editor);
exports.onSessionChange.call(editor, editor);
editor.on("changeSession", exports.onSessionChange.bind(editor));
editor.on("mousedown", onMouseDown);
editor.commands.addCommands(exports.commands.defaultCommands);
addAltCursorListeners(editor);
}
function addAltCursorListeners(editor){
var el = editor.textInput.getElement();
var altCursor = false;
var contentEl = editor.renderer.content;
el.addEventListener("keydown", function(e) {
if (e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey)) {
if (!altCursor) {
contentEl.style.cursor = "crosshair";
altCursor = true;
}
} else if (altCursor) {
contentEl.style.cursor = "";
}
});
el.addEventListener("keyup", reset);
el.addEventListener("blur", reset);
function reset() {
if (altCursor) {
contentEl.style.cursor = "";
altCursor = false;
}
}
}
exports.MultiSelect = MultiSelect;
});

View file

@ -0,0 +1,171 @@
/* vim:ts=4:sts=4:sw=4:
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Harutyun Amirjanyan <amirjanyan AT gmail DOT com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
if (typeof process !== "undefined") {
require("amd-loader");
}
define(function(require, exports, module) {
"use strict";
var EditSession = require("./edit_session").EditSession;
var Editor = require("./editor").Editor;
var MockRenderer = require("./test/mockrenderer").MockRenderer;
var Range = require("./range").Range;
var assert = require("./test/assertions");
var MultiSelect = require("./multi_select").MultiSelect;
var editor
var exec = function(name, times, args) {
do {
editor.commands.exec(name, editor, args);
} while(times --> 1)
};
var testRanges = function(str) {
assert.equal(editor.selection.getAllRanges() + "", str + "");
}
module.exports = {
name: "ACE multi_select.js",
"test: multiselect editing": function() {
var doc = new EditSession([
"w1.w2",
" wtt.w",
" wtt.w"
]);
editor = new Editor(new MockRenderer(), doc);
MultiSelect(editor);
editor.navigateFileEnd();
exec("selectMoreBefore", 3);
assert.ok(editor.inMultiSelectMode);
assert.equal(editor.selection.getAllRanges().length, 4);
var newLine = editor.session.getDocument().getNewLineCharacter();
var copyText = "wwww".split("").join(newLine);
assert.equal(editor.getCopyText(), copyText);
exec("insertstring", 1, "a");
exec("backspace", 2);
assert.equal(editor.session.getValue(), "w1.w2\ntt\ntt");
assert.equal(editor.selection.getAllRanges().length, 4);
exec("selectall");
assert.ok(!editor.inMultiSelectMode);
//assert.equal(editor.selection.getAllRanges().length, 1);
},
"test: multiselect navigation": function() {
var doc = new EditSession([
"w1.w2",
" wtt.w",
" wtt.we"
]);
editor = new Editor(new MockRenderer(), doc);
MultiSelect(editor);
editor.selectMoreLines(1);
testRanges("Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]");
assert.ok(editor.inMultiSelectMode);
exec("golinedown");
exec("gotolineend");
testRanges("Range: [1/9] -> [1/9],Range: [2/10] -> [2/10]");
exec("selectwordleft");
testRanges("Range: [1/8] -> [1/9],Range: [2/8] -> [2/10]");
exec("golinedown", 2);
assert.ok(!editor.inMultiSelectMode);
},
"test: multiselect session change": function() {
var doc = new EditSession([
"w1.w2",
" wtt.w",
" wtt.w"
]);
editor = new Editor(new MockRenderer(), doc);
MultiSelect(editor);
editor.selectMoreLines(1)
testRanges("Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]");
assert.ok(editor.inMultiSelectMode);
var doc2 = new EditSession(["w1"]);
editor.setSession(doc2);
assert.ok(!editor.inMultiSelectMode);
editor.setSession(doc);
assert.ok(editor.inMultiSelectMode);
},
"test: multiselect addRange": function() {
var doc = new EditSession([
"w1.w2",
" wtt.w",
" wtt.w"
]);
editor = new Editor(new MockRenderer(), doc);
MultiSelect(editor);
var selection = editor.selection;
var range1 = new Range(0, 2, 0, 4);
editor.selection.fromOrientedRange(range1);
var range2 = new Range(0, 3, 0, 4);
selection.addRange(range2);
assert.ok(!editor.inMultiSelectMode);
assert.ok(range2.isEqual(editor.selection.getRange()));
var range3 = new Range(0, 1, 0, 1);
selection.addRange(range3);
assert.ok(editor.inMultiSelectMode);
testRanges([range3, range2]);
var range4 = new Range(0, 0, 4, 0);
selection.addRange(range4);
assert.ok(!editor.inMultiSelectMode);
}
};
});
if (typeof module !== "undefined" && module === require.main) {
require("asyncjs").test.testcase(module.exports).exec()
}

View file

@ -111,7 +111,7 @@ var strictKeywords = {
"implements": true,
"interface": true,
"let": true,
"module": true,
//"module": true,
"package": true,
"private": true,
"protected": true,

View file

@ -69,13 +69,13 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
(function() {
/**
* Range.isEequal(range) -> Boolean
* Range.isEqual(range) -> Boolean
* - range (Range): A range to check against
*
* Returns `true` if and only if the starting row and column, and ending tow and column, are equivalent to those given by `range`.
*
**/
this.isEequal = function(range) {
this.isEqual = function(range) {
return this.start.row == range.start.row &&
this.end.row == range.end.row &&
this.start.column == range.start.column &&
@ -195,6 +195,18 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;
}
/**
* Range.intersects(range) -> Boolean
* - range (Range): A range to compare with
*
* Returns `true` if passed in `range` intersects with the one calling this method.
*
**/
this.intersects = function(range) {
var cmp = this.compareRange(range);
return (cmp == -1 || cmp == 0 || cmp == 1);
}
/**
* Range.isEnd(row, column) -> Boolean
* - row (Number): A row point to compare with
@ -202,7 +214,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
*
* Returns `true` if the caller's ending row point is the same as `row`, and if the caller's ending column is the same as `column`.
*
**/
**/
this.isEnd = function(row, column) {
return this.end.row == row && this.end.column == column;
}
@ -356,7 +368,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
return 0;
};
/**
/**
* Range.compareStart(row, column) -> Number
* - row (Number): A row point to compare with
* - column (Number): A column point to compare with
@ -386,7 +398,7 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
}
}
/**
/**
* Range.compareEnd(row, column) -> Number
* - row (Number): A row point to compare with
* - column (Number): A column point to compare with
@ -501,12 +513,6 @@ var Range = function(startRow, startColumn, endRow, endColumn) {
return Range.fromPoints(start || this.start, end || this.end);
};
/**
* Range.isEmpty() -> Boolean
*
* Checks if the range is empty; that is, the starting and ending points for row and column are equivalent. Returns `true` if the range is indeed empty.
*
**/
this.isEmpty = function() {
return (this.start.row == this.end.row && this.start.column == this.end.column);
};

231
lib/ace/range_list.js Normal file
View file

@ -0,0 +1,231 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Harutyun Amirjanyan <amirjanyan AT gmail DOT com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
"use strict";
var RangeList = function() {
this.ranges = [];
};
(function() {
this.comparePoints = function(p1, p2) {
return p1.row - p2.row || p1.column - p2.column;
};
this.pointIndex = function(pos, startIndex) {
var list = this.ranges;
for (var i = startIndex || 0; i < list.length; i++) {
var range = list[i];
var cmp = this.comparePoints(pos, range.end);
if (cmp > 0)
continue;
if (cmp == 0)
return i;
cmp = this.comparePoints(pos, range.start);
if (cmp >= 0)
return i;
return -i-1;
}
return -i - 1;
};
this.add = function(range) {
var startIndex = this.pointIndex(range.start);
if (startIndex < 0)
startIndex = -startIndex - 1;
var endIndex = this.pointIndex(range.end, startIndex);
if (endIndex < 0)
endIndex = -endIndex - 1;
else
endIndex++;
return this.ranges.splice(startIndex, endIndex - startIndex, range);
};
this.addList = function(list) {
var removed = [];
for (var i = list.length; i--; ) {
removed.push.call(removed, this.add(list[i]));
}
return removed;
};
this.substractPoint = function(pos) {
var i = this.pointIndex(pos);
if (i >= 0)
return this.ranges.splice(i, 1);
};
// merge overlapping ranges
this.merge = function() {
var removed = [];
var list = this.ranges;
var next = list[0], range;
for (var i = 1; i < list.length; i++) {
range = next;
next = list[i];
var cmp = this.comparePoints(range.end, next.start);
if (cmp < 0)
continue;
if (cmp == 0 && !(range.isEmpty() || next.isEmpty()))
continue;
if (this.comparePoints(range.end, next.end) < 0) {
range.end.row = next.end.row;
range.end.column = next.end.column;
}
list.splice(i, 1);
removed.push(next);
next = range;
i--;
}
return removed;
};
this.contains = function(row, column) {
return this.pointIndex({row: row, column: column}) >= 0;
};
this.containsPoint = function(pos) {
return this.pointIndex(pos) >= 0;
};
this.rangeAtPoint = function(pos) {
var i = this.pointIndex(pos);
if (i >= 0)
return this.ranges[i];
};
this.clipRows = function(startRow, endRow) {
var list = this.ranges;
if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow)
return [];
var startIndex = this.pointIndex({row: startRow, column: 0});
if (startIndex < 0)
startIndex = -startIndex - 1;
var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex);
if (endIndex < 0)
endIndex = -endIndex - 1;
var clipped = [];
for (var i = startIndex; i < endIndex; i++) {
clipped.push(list[i]);
}
return clipped;
};
this.removeAll = function() {
return this.ranges.splice(0, this.ranges.length);
};
this.attach = function(session) {
if (this.session)
this.detach();
this.session = session;
this.onChange = this.$onChange.bind(this);
this.session.on('change', this.onChange);
};
this.detach = function() {
if (!this.session)
return;
this.session.removeListener('change', this.onChange);
this.session = null;
};
this.$onChange = function(e) {
var changeRange = e.data.range;
if (e.data.action[0] == "i"){
var start = changeRange.start;
var end = changeRange.end;
} else {
var end = changeRange.start;
var start = changeRange.end;
}
var startRow = start.row;
var endRow = end.row;
var lineDif = endRow - startRow;
var colDiff = -start.column + end.column;
var ranges = this.ranges;
for (var i=0, n = ranges.length; i < n; i++) {
var r = ranges[i];
if (r.end.row < startRow)
continue;
if (r.start.row > startRow)
break;
if (r.start.row == startRow && r.start.column >= start.column ) {
r.start.column += colDiff;
r.start.row += lineDif;
}
if (r.end.row == startRow && r.end.column >= start.column) {
r.end.column += colDiff;
r.end.row += lineDif;
}
}
if (lineDif != 0 && i < n) {
for (; i < n; i++) {
var r = ranges[i];
r.start.row += lineDif;
r.end.row += lineDif;
}
}
};
}).call(RangeList.prototype);
exports.RangeList = RangeList;
});

170
lib/ace/range_list_test.js Normal file
View file

@ -0,0 +1,170 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Ajax.org Code Editor (ACE).
*
* The Initial Developer of the Original Code is
* Ajax.org B.V.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Fabian Jakobs <fabian AT ajax DOT org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
if (typeof process !== "undefined") {
require("amd-loader");
}
define(function(require, exports, module) {
"use strict";
var Range = require("./range").Range;
var RangeList = require("./range_list").RangeList;
var EditSession = require("./edit_session").EditSession;
var assert = require("./test/assertions");
function flatten(rangeList) {
var points = [];
rangeList.ranges.forEach(function(r) {
points.push(r.start.row, r.start.column, r.end.row, r.end.column)
})
return points;
}
function testRangeList(rangeList, points) {
assert.equal("" + flatten(rangeList), "" + points);
}
module.exports = {
name: "ACE range_list.js",
"test: rangeList pointIndex": function() {
var rangeList = new RangeList();
rangeList.ranges = [
new Range(1,2,3,4),
new Range(4,2,5,4),
new Range(8,8,9,9)
];
assert.equal(rangeList.pointIndex({row: 0, column: 1}), -1);
assert.equal(rangeList.pointIndex({row: 1, column: 2}), 0);
assert.equal(rangeList.pointIndex({row: 1, column: 3}), 0);
assert.equal(rangeList.pointIndex({row: 3, column: 4}), 0);
assert.equal(rangeList.pointIndex({row: 4, column: 1}), -2);
assert.equal(rangeList.pointIndex({row: 5, column: 1}), 1);
assert.equal(rangeList.pointIndex({row: 8, column: 9}), 2);
assert.equal(rangeList.pointIndex({row: 18, column: 9}), -4);
},
"test: rangeList add": function() {
var rangeList = new RangeList();
rangeList.addList([
new Range(9,0,9,1),
new Range(1,2,3,4),
new Range(8,8,9,9),
new Range(4,2,5,4),
new Range(3,20,3,24),
new Range(6,6,7,7)
]);
assert.equal(rangeList.ranges.length, 5);
rangeList.add(new Range(1,2,3,5));
assert.range(rangeList.ranges[0], 1,2,3,5);
assert.equal(rangeList.ranges.length, 5);
rangeList.add(new Range(7,7,7,7));
assert.range(rangeList.ranges[3], 7,7,7,7);
rangeList.add(new Range(7,8,7,8));
assert.range(rangeList.ranges[4], 7,8,7,8);
},
"test: rangeList add empty": function() {
var rangeList = new RangeList();
rangeList.addList([
new Range(7,10,7,10),
new Range(9,10,9,10),
new Range(8,10,8,10)
]);
assert.equal(rangeList.ranges.length, 3);
rangeList.add(new Range(9,10,9,10));
testRangeList(rangeList, [7,10,7,10,8,10,8,10,9,10,9,10]);
},
"test: rangeList merge": function() {
var rangeList = new RangeList();
rangeList.addList([
new Range(1,2,3,4),
new Range(4,2,5,4),
new Range(6,6,7,7),
new Range(8,8,9,9)
]);
var removed = [];
assert.equal(rangeList.ranges.length, 4);
rangeList.ranges[1].end.row = 7;
removed = rangeList.merge();
assert.equal(removed.length, 1);
assert.range(rangeList.ranges[1], 4,2,7,7);
assert.equal(rangeList.ranges.length, 3);
rangeList.ranges[0].end.row = 10;
removed = rangeList.merge();
assert.range(rangeList.ranges[0], 1,2,10,4);
assert.equal(removed.length, 2);
assert.equal(rangeList.ranges.length, 1);
rangeList.ranges.push(new Range(10,10,10,10));
rangeList.ranges.push(new Range(10,10,10,10));
removed = rangeList.merge();
assert.equal(rangeList.ranges.length, 2);
},
"test: rangeList remove": function() {
var rangeList = new RangeList();
var list = [
new Range(1,2,3,4),
new Range(4,2,5,4),
new Range(6,6,7,7),
new Range(8,8,9,9)
];
rangeList.addList(list);
assert.equal(rangeList.ranges.length, 4);
rangeList.substractPoint({row: 1, column: 2});
assert.equal(rangeList.ranges.length, 3);
rangeList.substractPoint({row: 6, column: 7});
assert.equal(rangeList.ranges.length, 2);
}
};
});
if (typeof module !== "undefined" && module === require.main) {
require("asyncjs").test.testcase(module.exports).exec()
}

View file

@ -130,6 +130,8 @@ var ScrollBar = function(parent) {
* Sets the scroll top of the scroll bar.
*
**/
// TODO: on chrome 17+ after for small zoom levels after this function
// this.element.scrollTop != scrollTop which makes page to scroll up.
this.setScrollTop = function(scrollTop) {
this.element.scrollTop = scrollTop;
};

View file

@ -67,18 +67,18 @@ var Selection = function(session) {
this.selectionLead = this.doc.createAnchor(0, 0);
this.selectionAnchor = this.doc.createAnchor(0, 0);
var _self = this;
var self = this;
this.selectionLead.on("change", function(e) {
_self._emit("changeCursor");
if (!_self.$isEmpty)
_self._emit("changeSelection");
if (!_self.$preventUpdateDesiredColumnOnChange && e.old.column != e.value.column)
_self.$updateDesiredColumn();
self._emit("changeCursor");
if (!self.$isEmpty)
self._emit("changeSelection");
if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column)
self.$desiredColumn = null;
});
this.selectionAnchor.on("change", function() {
if (!_self.$isEmpty)
_self._emit("changeSelection");
if (!self.$isEmpty)
self._emit("changeSelection");
});
};
@ -91,7 +91,7 @@ var Selection = function(session) {
*
* Returns `true` if the selection is empty.
**/
this.isEmpty = function() {
this.isEmpty = function() {
return (this.$isEmpty || (
this.selectionAnchor.row == this.selectionLead.row &&
this.selectionAnchor.column == this.selectionLead.column
@ -103,7 +103,7 @@ var Selection = function(session) {
*
* Returns `true` if the selection is a multi-line.
**/
this.isMultiLine = function() {
this.isMultiLine = function() {
if (this.isEmpty()) {
return false;
}
@ -116,7 +116,7 @@ var Selection = function(session) {
*
* Gets the current position of the cursor.
**/
this.getCursor = function() {
this.getCursor = function() {
return this.selectionLead.getPosition();
};
@ -127,7 +127,7 @@ var Selection = function(session) {
*
* Sets the row and column position of the anchor. This function also emits the `'changeSelection'` event.
**/
this.setSelectionAnchor = function(row, column) {
this.setSelectionAnchor = function(row, column) {
this.selectionAnchor.setPosition(row, column);
if (this.$isEmpty) {
@ -142,7 +142,7 @@ var Selection = function(session) {
* Returns an object containing the `row` and `column` of the calling selection anchor.
*
**/
this.getSelectionAnchor = function() {
this.getSelectionAnchor = function() {
if (this.$isEmpty)
return this.getSelectionLead()
else
@ -154,7 +154,7 @@ var Selection = function(session) {
*
* Returns an object containing the `row` and `column` of the calling selection lead.
**/
this.getSelectionLead = function() {
this.getSelectionLead = function() {
return this.selectionLead.getPosition();
};
@ -165,7 +165,7 @@ var Selection = function(session) {
* Shifts the selection up (or down, if [[Selection.isBackwards `isBackwards()`]] is true) the given number of columns.
*
**/
this.shiftSelection = function(columns) {
this.shiftSelection = function(columns) {
if (this.$isEmpty) {
this.moveCursorTo(this.selectionLead.row, this.selectionLead.column + columns);
return;
@ -191,7 +191,7 @@ var Selection = function(session) {
*
* Returns `true` if the selection is going backwards in the document.
**/
this.isBackwards = function() {
this.isBackwards = function() {
var anchor = this.selectionAnchor;
var lead = this.selectionLead;
return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));
@ -202,7 +202,7 @@ var Selection = function(session) {
*
* [Returns the [[Range `Range`]] for the selected text.]{: #Selection.getRange}
**/
this.getRange = function() {
this.getRange = function() {
var anchor = this.selectionAnchor;
var lead = this.selectionLead;
@ -222,7 +222,7 @@ var Selection = function(session) {
*
* [Empties the selection (by de-selecting it). This function also emits the `'changeSelection'` event.]{: #Selection.clearSelection}
**/
this.clearSelection = function() {
this.clearSelection = function() {
if (!this.$isEmpty) {
this.$isEmpty = true;
this._emit("changeSelection");
@ -234,7 +234,7 @@ var Selection = function(session) {
*
* Selects all the text in the document.
**/
this.selectAll = function() {
this.selectAll = function() {
var lastRow = this.doc.getLength() - 1;
this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);
this.moveCursorTo(0, 0);
@ -248,7 +248,7 @@ var Selection = function(session) {
* Sets the selection to the provided range.
*
**/
this.setSelectionRange = function(range, reverse) {
this.setSelectionRange = function(range, reverse) {
if (reverse) {
this.setSelectionAnchor(range.end.row, range.end.column);
this.selectTo(range.start.row, range.start.column);
@ -256,12 +256,7 @@ var Selection = function(session) {
this.setSelectionAnchor(range.start.row, range.start.column);
this.selectTo(range.end.row, range.end.column);
}
this.$updateDesiredColumn();
};
this.$updateDesiredColumn = function() {
var cursor = this.getCursor();
this.$desiredColumn = this.session.documentToScreenColumn(cursor.row, cursor.column);
this.$desiredColumn = null;
};
this.$moveSelection = function(mover) {
@ -280,7 +275,7 @@ var Selection = function(session) {
* Moves the selection cursor to the indicated row and column.
*
**/
this.selectTo = function(row, column) {
this.selectTo = function(row, column) {
this.$moveSelection(function() {
this.moveCursorTo(row, column);
});
@ -293,7 +288,7 @@ var Selection = function(session) {
* Moves the selection cursor to the row and column indicated by `pos`.
*
**/
this.selectToPosition = function(pos) {
this.selectToPosition = function(pos) {
this.$moveSelection(function() {
this.moveCursorToPosition(pos);
});
@ -304,7 +299,7 @@ var Selection = function(session) {
*
* Moves the selection up one row.
**/
this.selectUp = function() {
this.selectUp = function() {
this.$moveSelection(this.moveCursorUp);
};
@ -313,7 +308,7 @@ var Selection = function(session) {
*
* Moves the selection down one row.
**/
this.selectDown = function() {
this.selectDown = function() {
this.$moveSelection(this.moveCursorDown);
};
@ -322,7 +317,7 @@ var Selection = function(session) {
*
* Moves the selection right one column.
**/
this.selectRight = function() {
this.selectRight = function() {
this.$moveSelection(this.moveCursorRight);
};
@ -331,7 +326,7 @@ var Selection = function(session) {
*
* Moves the selection left one column.
**/
this.selectLeft = function() {
this.selectLeft = function() {
this.$moveSelection(this.moveCursorLeft);
};
@ -340,7 +335,7 @@ var Selection = function(session) {
*
* Moves the selection to the beginning of the current line.
**/
this.selectLineStart = function() {
this.selectLineStart = function() {
this.$moveSelection(this.moveCursorLineStart);
};
@ -349,7 +344,7 @@ var Selection = function(session) {
*
* Moves the selection to the end of the current line.
**/
this.selectLineEnd = function() {
this.selectLineEnd = function() {
this.$moveSelection(this.moveCursorLineEnd);
};
@ -358,7 +353,7 @@ var Selection = function(session) {
*
* Moves the selection to the end of the file.
**/
this.selectFileEnd = function() {
this.selectFileEnd = function() {
this.$moveSelection(this.moveCursorFileEnd);
};
@ -367,7 +362,7 @@ var Selection = function(session) {
*
* Moves the selection to the start of the file.
**/
this.selectFileStart = function() {
this.selectFileStart = function() {
this.$moveSelection(this.moveCursorFileStart);
};
@ -376,7 +371,7 @@ var Selection = function(session) {
*
* Moves the selection to the first word on the right.
**/
this.selectWordRight = function() {
this.selectWordRight = function() {
this.$moveSelection(this.moveCursorWordRight);
};
@ -385,7 +380,7 @@ var Selection = function(session) {
*
* Moves the selection to the first word on the left.
**/
this.selectWordLeft = function() {
this.selectWordLeft = function() {
this.$moveSelection(this.moveCursorWordLeft);
};
@ -394,7 +389,7 @@ var Selection = function(session) {
*
* Moves the selection to highlight the entire word.
**/
this.selectWord = function() {
this.selectWord = function() {
var cursor = this.getCursor();
var range = this.session.getWordRange(cursor.row, cursor.column);
this.setSelectionRange(range);
@ -405,7 +400,7 @@ var Selection = function(session) {
*
* Selects a word, including its right whitespace.
**/
this.selectAWord = function() {
this.selectAWord = function() {
var cursor = this.getCursor();
var range = this.session.getAWordRange(cursor.row, cursor.column);
this.setSelectionRange(range);
@ -416,7 +411,7 @@ var Selection = function(session) {
*
* Selects the entire line.
**/
this.selectLine = function() {
this.selectLine = function() {
var rowStart = this.selectionLead.row;
var rowEnd;
@ -438,7 +433,7 @@ var Selection = function(session) {
*
* Moves the cursor up one row.
**/
this.moveCursorUp = function() {
this.moveCursorUp = function() {
this.moveCursorBy(-1, 0);
};
@ -447,7 +442,7 @@ var Selection = function(session) {
*
* Moves the cursor down one row.
**/
this.moveCursorDown = function() {
this.moveCursorDown = function() {
this.moveCursorBy(1, 0);
};
@ -456,7 +451,7 @@ var Selection = function(session) {
*
* Moves the cursor left one column.
**/
this.moveCursorLeft = function() {
this.moveCursorLeft = function() {
var cursor = this.selectionLead.getPosition(),
fold;
@ -482,7 +477,7 @@ var Selection = function(session) {
*
* Moves the cursor right one column.
**/
this.moveCursorRight = function() {
this.moveCursorRight = function() {
var cursor = this.selectionLead.getPosition(),
fold;
if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) {
@ -508,7 +503,7 @@ var Selection = function(session) {
*
* Moves the cursor to the start of the line.
**/
this.moveCursorLineStart = function() {
this.moveCursorLineStart = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
var screenRow = this.session.documentToScreenRow(row, column);
@ -541,7 +536,7 @@ var Selection = function(session) {
*
* Moves the cursor to the end of the line.
**/
this.moveCursorLineEnd = function() {
this.moveCursorLineEnd = function() {
var lead = this.selectionLead;
var lastRowColumnPosition =
this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);
@ -556,7 +551,7 @@ var Selection = function(session) {
*
* Moves the cursor to the end of the file.
**/
this.moveCursorFileEnd = function() {
this.moveCursorFileEnd = function() {
var row = this.doc.getLength() - 1;
var column = this.doc.getLine(row).length;
this.moveCursorTo(row, column);
@ -567,7 +562,7 @@ var Selection = function(session) {
*
* Moves the cursor to the start of the file.
**/
this.moveCursorFileStart = function() {
this.moveCursorFileStart = function() {
this.moveCursorTo(0, 0);
};
@ -576,7 +571,7 @@ var Selection = function(session) {
*
* Moves the cursor to the word on the right.
**/
this.moveCursorWordRight = function() {
this.moveCursorWordRight = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
var line = this.doc.getLine(row);
@ -623,7 +618,7 @@ var Selection = function(session) {
*
* Moves the cursor to the word on the left.
**/
this.moveCursorWordLeft = function() {
this.moveCursorWordLeft = function() {
var row = this.selectionLead.row;
var column = this.selectionLead.column;
@ -676,14 +671,20 @@ var Selection = function(session) {
*
* Moves the cursor to position indicated by the parameters. Negative numbers move the cursor backwards in the document.
**/
this.moveCursorBy = function(rows, chars) {
this.moveCursorBy = function(rows, chars) {
var screenPos = this.session.documentToScreenPosition(
this.selectionLead.row,
this.selectionLead.column
);
var screenCol = (chars === 0 && this.$desiredColumn) || screenPos.column;
var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenCol);
if (chars === 0) {
if (this.$desiredColumn)
screenPos.column = this.$desiredColumn;
else
this.$desiredColumn = screenPos.column;
}
var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column);
// move the cursor and update the desired column
this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0);
@ -695,19 +696,19 @@ var Selection = function(session) {
*
* Moves the selection to the position indicated by its `row` and `column`.
**/
this.moveCursorToPosition = function(position) {
this.moveCursorToPosition = function(position) {
this.moveCursorTo(position.row, position.column);
};
/**
* Selection.moveCursorTo(row, column, preventUpdateDesiredColumn) -> Void
* Selection.moveCursorTo(row, column, keepDesiredColumn) -> Void
* - row (Number): The row to move to
* - column (Number): The column to move to
* - preventUpdateDesiredColumn (Boolean): [If `true`, the cursor move does not respect the previous column]{: #preventUpdateBool}
* - keepDesiredColumn (Boolean): [If `true`, the cursor move does not respect the previous column]{: #preventUpdateBool}
*
* Moves the cursor to the row and column provided. [If `preventUpdateDesiredColumn` is `true`, then the cursor stays in the same column position as its original point.]{: #preventUpdateBoolDesc}
**/
this.moveCursorTo = function(row, column, preventUpdateDesiredColumn) {
this.moveCursorTo = function(row, column, keepDesiredColumn) {
// Ensure the row/column is not inside of a fold.
var fold = this.session.getFoldAt(row, column, 1);
if (fold) {
@ -715,29 +716,55 @@ var Selection = function(session) {
column = fold.start.column;
}
this.$preventUpdateDesiredColumnOnChange = true;
this.$keepDesiredColumnOnChange = true;
this.selectionLead.setPosition(row, column);
this.$preventUpdateDesiredColumnOnChange = false;
this.$keepDesiredColumnOnChange = false;
if (!preventUpdateDesiredColumn)
this.$updateDesiredColumn(this.selectionLead.column);
if (!keepDesiredColumn)
this.$desiredColumn = null;
};
/**
* Selection.moveCursorToScreen(row, column, preventUpdateDesiredColumn) -> Void
* Selection.moveCursorToScreen(row, column, keepDesiredColumn) -> Void
* - row (Number): The row to move to
* - column (Number): The column to move to
* - preventUpdateDesiredColumn (Boolean): {:preventUpdateBool}
* - keepDesiredColumn (Boolean): {:preventUpdateBool}
*
* Moves the cursor to the screen position indicated by row and column. {:preventUpdateBoolDesc}
**/
this.moveCursorToScreen = function(row, column, preventUpdateDesiredColumn) {
this.moveCursorToScreen = function(row, column, keepDesiredColumn) {
var pos = this.session.screenToDocumentPosition(row, column);
row = pos.row;
column = pos.column;
this.moveCursorTo(row, column, preventUpdateDesiredColumn);
this.moveCursorTo(pos.row, pos.column, keepDesiredColumn);
};
// remove listeners from document
this.detach = function() {
this.selectionLead.detach();
this.selectionAnchor.detach();
this.session = this.doc = null;
}
this.fromOrientedRange = function(range) {
this.setSelectionRange(range, range.cursor == range.start);
this.$desiredColumn = range.desiredColumn || this.$desiredColumn;
}
this.toOrientedRange = function(range) {
var r = this.getRange();
if (range) {
range.start.column = r.start.column;
range.start.row = r.start.row;
range.end.column = r.end.column;
range.end.row = r.end.row;
} else {
range = r;
}
range.cursor = this.isBackwards() ? range.start : range.end;
range.desiredColumn = this.$desiredColumn;
return range;
}
}).call(Selection.prototype);
exports.Selection = Selection;

View file

@ -73,7 +73,7 @@ var Split = function(container, theme, splits) {
this.$splits = 0;
this.$editorCSS = "";
this.$editors = [];
this.$oriantation = this.BESIDE;
this.$orientation = this.BESIDE;
this.setSplits(splits || 1);
this.$cEditor = this.$editors[0];
@ -304,27 +304,27 @@ var Split = function(container, theme, splits) {
};
/** internal
* Split.getOriantation() -> Number
* Split.getOrientation() -> Number
*
* Returns the orientation.
*
**/
this.getOriantation = function() {
return this.$oriantation;
this.getOrientation = function() {
return this.$orientation;
};
/** internal
* Split.setOriantation(oriantation) -> Void
* Split.setOrientation(oriantation) -> Void
* - oriantation (Number):
*
* Sets the orientation.
*
**/
this.setOriantation = function(oriantation) {
if (this.$oriantation == oriantation) {
this.setOrientation = function(orientation) {
if (this.$orientation == orientation) {
return;
}
this.$oriantation = oriantation;
this.$orientation = orientation;
this.resize();
};
@ -339,7 +339,7 @@ var Split = function(container, theme, splits) {
var height = this.$container.clientHeight;
var editor;
if (this.$oriantation == this.BESIDE) {
if (this.$orientation == this.BESIDE) {
var editorWidth = width / this.$splits;
for (var i = 0; i < this.$splits; i++) {
editor = this.$editors[i];

View file

@ -9,96 +9,116 @@ var passed = 0
var failed = 0
var log = document.getElementById("log")
var tests = [
require("ace/anchor_test"),
require("ace/commands/command_manager_test"),
require("ace/document_test"),
require("ace/edit_session_test"),
require("ace/editor_change_document_test"),
require("ace/editor_highlight_selected_word_test"),
require("ace/editor_navigation_test"),
require("ace/editor_text_edit_test"),
require("ace/ext/static_highlight_test"),
require("ace/layer/text_test"),
require("ace/lib/event_emitter_test"),
require("ace/mode/coffee/parser_test"),
require("ace/mode/coffee_tokenizer_test"),
require("ace/mode/coldfusion_test"),
require("ace/mode/css_test"),
require("ace/mode/css_tokenizer_test"),
require("ace/mode/css_worker"),
require("ace/mode/html_test"),
require("ace/mode/html_tokenizer_test"),
require("ace/mode/javascript_test"),
require("ace/mode/javascript_tokenizer_test"),
require("ace/mode/javascript_worker_test"),
require("ace/mode/python_test"),
require("ace/mode/ruby_tokenizer_test"),
require("ace/mode/text_test"),
require("ace/mode/xml_test"),
require("ace/mode/xml_tokenizer_test"),
require("ace/mode/folding/cstyle_test"),
require("ace/mode/folding/html_test"),
require("ace/mode/folding/pythonic_test"),
require("ace/mode/folding/xml_test"),
require("ace/range_test"),
require("ace/search_test"),
require("ace/selection_test"),
require("ace/token_iterator_test"),
require("ace/virtual_renderer_test")
]
var testNames = [
"ace/anchor_test",
"ace/commands/command_manager_test",
"ace/document_test",
"ace/edit_session_test",
"ace/editor_change_document_test",
"ace/editor_highlight_selected_word_test",
"ace/editor_navigation_test",
"ace/editor_text_edit_test",
"ace/ext/static_highlight_test",
"ace/layer/text_test",
"ace/lib/event_emitter_test",
"ace/mode/coffee/parser_test",
"ace/mode/coffee_highlight_rules_test",
"ace/mode/coldfusion_test",
"ace/mode/css_test",
"ace/mode/css_highlight_rules_test",
"ace/mode/css_worker",
"ace/mode/html_test",
"ace/mode/html_highlight_rules_test",
"ace/mode/javascript_test",
"ace/mode/javascript_highlight_rules_test",
"ace/mode/javascript_worker_test",
"ace/mode/python_test",
"ace/mode/ruby_highlight_rules_test",
"ace/mode/text_test",
"ace/mode/xml_test",
"ace/mode/xml_highlight_rules_test",
"ace/mode/folding/cstyle_test",
"ace/mode/folding/html_test",
"ace/mode/folding/pythonic_test",
"ace/mode/folding/xml_test",
"ace/multi_select_test",
"ace/range_test",
"ace/range_list_test",
"ace/search_test",
"ace/selection_test",
"ace/token_iterator_test",
"ace/virtual_renderer_test"
];
async.list(tests)
.expand(function(test) {
return AsyncTest.testcase(test)
}, AsyncTest.TestGenerator)
.run()
.each(function(test, next) {
var node = document.createElement("div");
node.className = test.passed ? "passed" : "failed";
var html = ["<a href='?'>all tests</a><br>"];
for (var i in testNames) {
var href = testNames[i];
html.push("<a href='?", href, "'>", href.replace(/^ace\//, "") ,"</a><br>");
}
var name = test.name
if (test.suiteName)
name = test.suiteName + ": " + test.name
var nav = document.createElement("div");
nav.innerHTML = html.join("");
nav.style.cssText = "position:absolute;right:0;top:0";
document.body.appendChild(nav);
var msg = "[" + test.count + "/" + test.index + "] " + name + " " + (test.passed ? "OK" : "FAIL")
if (!test.passed) {
if (test.err.stack)
var err = test.err.stack
if (location.search)
testNames = location.search.substr(1).split(",")
require(testNames, function() {
var tests = testNames.map(require);
async.list(tests)
.expand(function(test) {
return AsyncTest.testcase(test)
}, AsyncTest.TestGenerator)
.run()
.each(function(test, next) {
var node = document.createElement("div");
node.className = test.passed ? "passed" : "failed";
var name = test.name
if (test.suiteName)
name = test.suiteName + ": " + test.name
var msg = "[" + test.count + "/" + test.index + "] " + name + " " + (test.passed ? "OK" : "FAIL")
if (!test.passed) {
if (test.err.stack)
var err = test.err.stack
else
var err = test.err
console.error(msg);
console.error(err);
msg += "<pre class='error'>" + err + "</pre>";
} else {
console.log(msg);
}
node.innerHTML = msg;
log.appendChild(node);
next()
})
.each(function(test) {
if (test.passed)
passed += 1
else
var err = test.err
console.error(msg);
console.error(err);
msg += "<pre class='error'>" + err + "</pre>";
} else {
console.log(msg);
}
node.innerHTML = msg;
log.appendChild(node);
next()
})
.each(function(test) {
if (test.passed)
passed += 1
else
failed += 1
})
.end(function() {
log.innerHTML += [
"<div class='summary'>",
"<br>",
"Summary: <br>",
"<br>",
"Total number of tests: " + (passed + failed) + "<br>",
(passed ? "Passed tests: " + passed + "<br>" : ""),
(failed ? "Failed tests: " + failed + "<br>" : "")
].join("")
console.log("Total number of tests: " + (passed + failed));
console.log("Passed tests: " + passed);
console.log("Failed tests: " + failed);
})
failed += 1
})
.end(function() {
log.innerHTML += [
"<div class='summary'>",
"<br>",
"Summary: <br>",
"<br>",
"Total number of tests: " + (passed + failed) + "<br>",
(passed ? "Passed tests: " + passed + "<br>" : ""),
(failed ? "Failed tests: " + failed + "<br>" : "")
].join("")
console.log("Total number of tests: " + (passed + failed));
console.log("Passed tests: " + passed);
console.log("Failed tests: " + failed);
})
});
});

View file

@ -81,6 +81,12 @@ MockRenderer.prototype.getTextAreaContainer = function() {
return this.container;
};
MockRenderer.prototype.addGutterDecoration = function() {
};
MockRenderer.prototype.removeGutterDecoration = function() {
};
MockRenderer.prototype.moveTextAreaToCursor = function() {
};
@ -174,6 +180,12 @@ MockRenderer.prototype.visualizeFocus = function() {
MockRenderer.prototype.setAnnotations = function() {
};
MockRenderer.prototype.setStyle = function() {
};
MockRenderer.prototype.unsetStyle = function() {
};
MockRenderer.prototype.textToScreenCoordinates = function() {
return {
pageX: 0,

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #000000;\
}\
\
\
.ace-clouds .ace_marker-layer .ace_selection {\
background: #BDD5FC;\
}\
\
.ace-clouds.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #FFFFFF;\
border-radius: 2px;\
}\
\
.ace-clouds .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-clouds .ace_marker-layer .ace_selected_word {\
border: 1px solid #BDD5FC;\
}\
\
\
.ace-clouds .ace_invisible {\
color: #BFBFBF;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #7DA5DC;\
}\
\
\
.ace-clouds-midnight .ace_marker-layer .ace_selection {\
background: #000000;\
}\
\
.ace-clouds-midnight.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #191919;\
border-radius: 2px;\
}\
\
.ace-clouds-midnight .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-clouds-midnight .ace_marker-layer .ace_selected_word {\
border: 1px solid #000000;\
}\
\
\
.ace-clouds-midnight .ace_invisible {\
color: #BFBFBF;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #FFFFFF;\
}\
\
\
.ace-cobalt .ace_marker-layer .ace_selection {\
background: rgba(179, 101, 57, 0.75);\
}\
\
.ace-cobalt.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #002240;\
border-radius: 2px;\
}\
\
.ace-cobalt .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-cobalt .ace_marker-layer .ace_selected_word {\
border: 1px solid rgba(179, 101, 57, 0.75);\
}\
\
\
.ace-cobalt .ace_invisible {\
color: rgba(255, 255, 255, 0.15);\
}\
@ -109,6 +114,14 @@ exports.cssText = "\
color:#FF628C;\
}\
\
.ace-cobalt .ace_constant.ace_character, {\
color:#FF628C;\
}\
\
.ace-cobalt .ace_constant.ace_character.ace_escape, {\
color:#FF628C;\
}\
\
.ace-cobalt .ace_invalid {\
color:#F8F8F8;\
background-color:#800F00;\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #000000;\
}\
\
\
.ace-dawn .ace_marker-layer .ace_selection {\
background: rgba(39, 95, 255, 0.30);\
}\
\
.ace-dawn.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #F9F9F9;\
border-radius: 2px;\
}\
\
.ace-dawn .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-dawn .ace_marker-layer .ace_selected_word {\
border: 1px solid rgba(39, 95, 255, 0.30);\
}\
\
\
.ace-dawn .ace_invisible {\
color: rgba(75, 75, 126, 0.50);\
}\
@ -109,6 +114,14 @@ exports.cssText = "\
color:#811F24;\
}\
\
.ace-dawn .ace_constant.ace_character, {\
color:#811F24;\
}\
\
.ace-dawn .ace_constant.ace_character.ace_escape, {\
color:#811F24;\
}\
\
.ace-dawn .ace_invalid.ace_illegal {\
text-decoration:underline;\
font-style:italic;\

View file

@ -67,7 +67,7 @@ exports.cssText = ".ace-eclipse .ace_editor {\
}\
\
.ace-eclipse .ace_cursor {\
border-left: 1px solid black;\
border-left: 2px solid black;\
}\
\
.ace-eclipse .ace_line .ace_storage,\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #91FF00;\
}\
\
\
.ace-idle-fingers .ace_marker-layer .ace_selection {\
background: rgba(90, 100, 126, 0.88);\
}\
\
.ace-idle-fingers.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #323232;\
border-radius: 2px;\
}\
\
.ace-idle-fingers .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-idle-fingers .ace_marker-layer .ace_selected_word {\
border: 1px solid rgba(90, 100, 126, 0.88);\
}\
\
\
.ace-idle-fingers .ace_invisible {\
color: #404040;\
}\
@ -109,6 +114,14 @@ exports.cssText = "\
color:#6C99BB;\
}\
\
.ace-idle-fingers .ace_constant.ace_character, {\
color:#6C99BB;\
}\
\
.ace-idle-fingers .ace_constant.ace_character.ace_escape, {\
color:#6C99BB;\
}\
\
.ace-idle-fingers .ace_invalid {\
color:#FFFFFF;\
background-color:#FF0000;\
@ -158,7 +171,7 @@ color:#BC9458;\
\
.ace-idle-fingers .ace_collab.ace_user1 {\
color:#323232;\
background-color:#FFF980; \
background-color:#FFF980;\
}";
var dom = require("../lib/dom");

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #FF9900;\
}\
\
\
.ace-kr-theme .ace_marker-layer .ace_selection {\
background: rgba(170, 0, 255, 0.45);\
}\
\
.ace-kr-theme.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #0B0A09;\
border-radius: 2px;\
}\
\
.ace-kr-theme .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-kr-theme .ace_marker-layer .ace_selected_word {\
border: 1px solid rgba(170, 0, 255, 0.45);\
}\
\
\
.ace-kr-theme .ace_invisible {\
color: rgba(255, 177, 111, 0.32);\
}\
@ -109,6 +114,14 @@ exports.cssText = "\
color:rgba(210, 117, 24, 0.76);\
}\
\
.ace-kr-theme .ace_constant.ace_character, {\
color:rgba(210, 117, 24, 0.76);\
}\
\
.ace-kr-theme .ace_constant.ace_character.ace_escape, {\
color:rgba(210, 117, 24, 0.76);\
}\
\
.ace-kr-theme .ace_invalid {\
color:#F8F8F8;\
background-color:#A41300;\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #FFFFFF;\
}\
\
\
.ace-merbivore .ace_marker-layer .ace_selection {\
background: #454545;\
}\
\
.ace-merbivore.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #161616;\
border-radius: 2px;\
}\
\
.ace-merbivore .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-merbivore .ace_marker-layer .ace_selected_word {\
border: 1px solid #454545;\
}\
\
\
.ace-merbivore .ace_invisible {\
color: #404040;\
}\
@ -109,6 +114,14 @@ exports.cssText = "\
color:#1EDAFB;\
}\
\
.ace-merbivore .ace_constant.ace_character, {\
color:#1EDAFB;\
}\
\
.ace-merbivore .ace_constant.ace_character.ace_escape, {\
color:#1EDAFB;\
}\
\
.ace-merbivore .ace_constant.ace_language {\
color:#FDC251;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #FFFFFF;\
}\
\
\
.ace-merbivore-soft .ace_marker-layer .ace_selection {\
background: #494949;\
}\
\
.ace-merbivore-soft.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #1C1C1C;\
border-radius: 2px;\
}\
\
.ace-merbivore-soft .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-merbivore-soft .ace_marker-layer .ace_selected_word {\
border: 1px solid #494949;\
}\
\
\
.ace-merbivore-soft .ace_invisible {\
color: #404040;\
}\
@ -109,6 +114,14 @@ exports.cssText = "\
color:#68C1D8;\
}\
\
.ace-merbivore-soft .ace_constant.ace_character, {\
color:#68C1D8;\
}\
\
.ace-merbivore-soft .ace_constant.ace_character.ace_escape, {\
color:#68C1D8;\
}\
\
.ace-merbivore-soft .ace_constant.ace_language {\
color:#E1C582;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #FFFFFF;\
}\
\
\
.ace-mono-industrial .ace_marker-layer .ace_selection {\
background: rgba(145, 153, 148, 0.40);\
}\
\
.ace-mono-industrial.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #222C28;\
border-radius: 2px;\
}\
\
.ace-mono-industrial .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-mono-industrial .ace_marker-layer .ace_selected_word {\
border: 1px solid rgba(145, 153, 148, 0.40);\
}\
\
\
.ace-mono-industrial .ace_invisible {\
color: rgba(102, 108, 104, 0.50);\
}\
@ -113,6 +118,14 @@ exports.cssText = "\
color:#E98800;\
}\
\
.ace-mono-industrial .ace_constant.ace_character, {\
color:#E98800;\
}\
\
.ace-mono-industrial .ace_constant.ace_character.ace_escape, {\
color:#E98800;\
}\
\
.ace-mono-industrial .ace_constant.ace_numeric {\
color:#E98800;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #F8F8F0;\
}\
\
\
.ace-monokai .ace_marker-layer .ace_selection {\
background: #49483E;\
}\
\
.ace-monokai.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #272822;\
border-radius: 2px;\
}\
\
.ace-monokai .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-monokai .ace_marker-layer .ace_selected_word {\
border: 1px solid #49483E;\
}\
\
\
.ace-monokai .ace_invisible {\
color: #49483E;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #A7A7A7;\
}\
\
\
.ace-pastel-on-dark .ace_marker-layer .ace_selection {\
background: rgba(221, 240, 255, 0.20);\
}\
\
.ace-pastel-on-dark.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #2C2828;\
border-radius: 2px;\
}\
\
.ace-pastel-on-dark .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-pastel-on-dark .ace_marker-layer .ace_selected_word {\
border: 1px solid rgba(221, 240, 255, 0.20);\
}\
\
\
.ace-pastel-on-dark .ace_invisible {\
color: rgba(255, 255, 255, 0.25);\
}\
@ -113,6 +118,14 @@ exports.cssText = "\
color:#4FB7C5;\
}\
\
.ace-pastel-on-dark .ace_constant.ace_character, {\
color:#4FB7C5;\
}\
\
.ace-pastel-on-dark .ace_constant.ace_character.ace_escape, {\
color:#4FB7C5;\
}\
\
.ace-pastel-on-dark .ace_constant.ace_language {\
color:#DE8E30;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #D30102;\
}\
\
\
.ace-solarized-dark .ace_marker-layer .ace_selection {\
background: #073642;\
}\
\
.ace-solarized-dark.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #002B36;\
border-radius: 2px;\
}\
\
.ace-solarized-dark .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-solarized-dark .ace_marker-layer .ace_selected_word {\
border: 1px solid #073642;\
}\
\
\
.ace-solarized-dark .ace_invisible {\
color: rgba(147, 161, 161, 0.50);\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #000000;\
}\
\
\
.ace-solarized-light .ace_marker-layer .ace_selection {\
background: #073642;\
}\
\
.ace-solarized-light.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #FDF6E3;\
border-radius: 2px;\
}\
\
.ace-solarized-light .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-solarized-light .ace_marker-layer .ace_selected_word {\
border: 1px solid #073642;\
}\
\
\
.ace-solarized-light .ace_invisible {\
color: rgba(147, 161, 161, 0.50);\
}\

View file

@ -84,6 +84,10 @@ exports.cssText = ".ace-tm .ace_editor {\
color: blue;\
}\
\
.ace-tm .ace_line .ace_constant {\
color: rgb(197, 6, 11);\
}\
\
.ace-tm .ace_line .ace_constant.ace_buildin {\
color: rgb(88, 72, 246);\
}\
@ -165,7 +169,10 @@ exports.cssText = ".ace-tm .ace_editor {\
.ace-tm .ace_marker-layer .ace_selection {\
background: rgb(181, 213, 255);\
}\
\
.ace-tm.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px white;\
border-radius: 2px;\
}\
.ace-tm .ace_marker-layer .ace_step {\
background: rgb(252, 255, 0);\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #AEAFAD;\
}\
\
\
.ace-tomorrow .ace_marker-layer .ace_selection {\
background: #D6D6D6;\
}\
\
.ace-tomorrow.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #FFFFFF;\
border-radius: 2px;\
}\
\
.ace-tomorrow .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-tomorrow .ace_marker-layer .ace_selected_word {\
border: 1px solid #D6D6D6;\
}\
\
\
.ace-tomorrow .ace_invisible {\
color: #D1D1D1;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #AEAFAD;\
}\
\
\
.ace-tomorrow-night .ace_marker-layer .ace_selection {\
background: #373B41;\
}\
\
.ace-tomorrow-night.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #1D1F21;\
border-radius: 2px;\
}\
\
.ace-tomorrow-night .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-tomorrow-night .ace_marker-layer .ace_selected_word {\
border: 1px solid #373B41;\
}\
\
\
.ace-tomorrow-night .ace_invisible {\
color: #4B4E55;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #FFFFFF;\
}\
\
\
.ace-tomorrow-night-blue .ace_marker-layer .ace_selection {\
background: #003F8E;\
}\
\
.ace-tomorrow-night-blue.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #002451;\
border-radius: 2px;\
}\
\
.ace-tomorrow-night-blue .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-tomorrow-night-blue .ace_marker-layer .ace_selected_word {\
border: 1px solid #003F8E;\
}\
\
\
.ace-tomorrow-night-blue .ace_invisible {\
color: #404F7D;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #9F9F9F;\
}\
\
\
.ace-tomorrow-night-bright .ace_marker-layer .ace_selection {\
background: #424242;\
}\
\
.ace-tomorrow-night-bright.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #000000;\
border-radius: 2px;\
}\
\
.ace-tomorrow-night-bright .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-tomorrow-night-bright .ace_marker-layer .ace_selected_word {\
border: 1px solid #424242;\
}\
\
\
.ace-tomorrow-night-bright .ace_invisible {\
color: #343434;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #CCCCCC;\
}\
\
\
.ace-tomorrow-night-eighties .ace_marker-layer .ace_selection {\
background: #515151;\
}\
\
.ace-tomorrow-night-eighties.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #2D2D2D;\
border-radius: 2px;\
}\
\
.ace-tomorrow-night-eighties .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-tomorrow-night-eighties .ace_marker-layer .ace_selected_word {\
border: 1px solid #515151;\
}\
\
\
.ace-tomorrow-night-eighties .ace_invisible {\
color: #6A6A6A;\
}\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #A7A7A7;\
}\
\
\
.ace-twilight .ace_marker-layer .ace_selection {\
background: rgba(221, 240, 255, 0.20);\
}\
\
.ace-twilight.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #141414;\
border-radius: 2px;\
}\
\
.ace-twilight .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-twilight .ace_marker-layer .ace_selected_word {\
border: 1px solid rgba(221, 240, 255, 0.20);\
}\
\
\
.ace-twilight .ace_invisible {\
color: rgba(255, 255, 255, 0.25);\
}\
@ -109,6 +114,14 @@ exports.cssText = "\
color:#CF6A4C;\
}\
\
.ace-twilight .ace_constant.ace_character, {\
color:#CF6A4C;\
}\
\
.ace-twilight .ace_constant.ace_character.ace_escape, {\
color:#CF6A4C;\
}\
\
.ace-twilight .ace_invalid.ace_illegal {\
color:#F8F8F8;\
background-color:rgba(86, 45, 86, 0.75);\

View file

@ -75,11 +75,16 @@ exports.cssText = "\
border-left: 0px;\
border-bottom: 1px solid #FFFFFF;\
}\
\
\
.ace-vibrant-ink .ace_marker-layer .ace_selection {\
background: #6699CC;\
}\
\
.ace-vibrant-ink.multiselect .ace_selection.start {\
box-shadow: 0 0 3px 0px #0F0F0F;\
border-radius: 2px;\
}\
\
.ace-vibrant-ink .ace_marker-layer .ace_step {\
background: rgb(198, 219, 174);\
}\
@ -96,7 +101,7 @@ exports.cssText = "\
.ace-vibrant-ink .ace_marker-layer .ace_selected_word {\
border: 1px solid #6699CC;\
}\
\
\
.ace-vibrant-ink .ace_invisible {\
color: #404040;\
}\
@ -109,6 +114,14 @@ exports.cssText = "\
color:#339999;\
}\
\
.ace-vibrant-ink .ace_constant.ace_character, {\
color:#339999;\
}\
\
.ace-vibrant-ink .ace_constant.ace_character.ace_escape, {\
color:#339999;\
}\
\
.ace-vibrant-ink .ace_constant.ace_numeric {\
color:#99CC99;\
}\

View file

@ -139,9 +139,8 @@ var Tokenizer = function(rules, flag) {
else
type = rule.token;
var next = rule.next;
if (next && next !== currentState) {
currentState = next;
if (rule.next) {
currentState = rule.next;
state = this.rules[currentState];
mapping = this.matchMappings[currentState];
lastIndex = re.lastIndex;

View file

@ -76,13 +76,13 @@ dom.importCssString(editorCss, "ace_editor");
var VirtualRenderer = function(container, theme) {
var _self = this;
this.container = container;
// 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);
dom.addCssClass(container, "ace_editor");
this.setTheme(theme);
@ -100,8 +100,8 @@ var VirtualRenderer = function(container, theme) {
this.scroller.appendChild(this.content);
this.$gutterLayer = new GutterLayer(this.$gutter);
this.$gutterLayer.on("changeGutterWidth", this.onResize.bind(this, true));
this.$gutterLayer.on("changeGutterWidth", this.onResize.bind(this, true));
this.$markerBack = new MarkerLayer(this.content);
var textLayer = this.$textLayer = new TextLayer(this.content);
@ -119,6 +119,8 @@ var VirtualRenderer = function(container, theme) {
this.$horizScroll = true;
this.$horizScrollAlwaysVisible = true;
this.$animatedScroll = false;
this.scrollBar = new ScrollBar(container);
this.scrollBar.addEventListener("scroll", function(e) {
_self.session.setScrollTop(e.data);
@ -126,11 +128,18 @@ var VirtualRenderer = function(container, theme) {
this.scrollTop = 0;
this.scrollLeft = 0;
event.addListener(this.scroller, "scroll", function() {
var scrollLeft = _self.scroller.scrollLeft;
_self.scrollLeft = scrollLeft;
_self.session.setScrollLeft(scrollLeft);
if (scrollLeft == 0) {
_self.$gutter.className = "ace_gutter";
}
else {
_self.$gutter.className = "ace_gutter horscroll";
}
});
this.cursorPos = {
@ -316,6 +325,26 @@ var VirtualRenderer = function(container, theme) {
return this.session.adjustWrapLimit(limit);
};
/**
* VirtualRenderer.setAnimatedScroll(shouldAnimate) -> Void
* - shouldAnimate (Boolean): Set to `true` to show animated scrolls
*
* Identifies whether you want to have an animated scroll or not.
*
**/
this.setAnimatedScroll = function(shouldAnimate){
this.$animatedScroll = shouldAnimate;
};
/**
* VirtualRenderer.getAnimatedScroll() -> Boolean
*
* Returns whether an animated scroll happens or not.
**/
this.getAnimatedScroll = function() {
return this.$animatedScroll;
};
/**
* VirtualRenderer.setShowInvisibles(showInvisibles) -> Void
* - showInvisibles (Boolean): Set to `true` to show invisibles
@ -331,7 +360,7 @@ var VirtualRenderer = function(container, theme) {
/**
* VirtualRenderer.getShowInvisibles() -> Boolean
*
* Returns whether or not invisible characters are being shown or not.
* Returns whether invisible characters are being shown or not.
**/
this.getShowInvisibles = function() {
return this.$textLayer.showInvisibles;
@ -354,7 +383,7 @@ var VirtualRenderer = function(container, theme) {
/**
* VirtualRenderer.getShowPrintMargin() -> Boolean
*
* Returns whether or not the print margin is being shown or not.
* Returns whetherthe print margin is being shown or not.
**/
this.getShowPrintMargin = function() {
return this.$showPrintMargin;
@ -377,7 +406,7 @@ var VirtualRenderer = function(container, theme) {
/**
* VirtualRenderer.getPrintMarginColumn() -> Boolean
*
* Returns whether or not the print margin column is being shown or not.
* Returns whether the print margin column is being shown or not.
**/
this.getPrintMarginColumn = function() {
return this.$printMarginColumn;
@ -464,7 +493,7 @@ var VirtualRenderer = function(container, theme) {
// this persists in IE9
if (useragent.isIE)
return;
if (this.layerConfig.lastRow === 0)
return;
@ -538,7 +567,7 @@ var VirtualRenderer = function(container, theme) {
/**
* VirtualRenderer.getHScrollBarAlwaysVisible() -> Boolean
*
* Returns whether or not the horizontal scrollbar is set to be always visible.
* Returns whether the horizontal scrollbar is set to be always visible.
**/
this.getHScrollBarAlwaysVisible = function() {
return this.$horizScrollAlwaysVisible;
@ -579,13 +608,13 @@ var VirtualRenderer = function(container, theme) {
// horizontal scrolling
if (changes & this.CHANGE_H_SCROLL) {
this.scroller.scrollLeft = this.scrollLeft;
// read the value after writing it since the value might get clipped
var scrollLeft = this.scroller.scrollLeft;
this.scrollLeft = scrollLeft;
this.session.setScrollLeft(scrollLeft);
}
// full
if (changes & this.CHANGE_FULL) {
this.$textLayer.checkForSizeChanges();
@ -937,21 +966,27 @@ var VirtualRenderer = function(container, theme) {
this.session.setScrollTop(row * this.lineHeight);
};
/**
* VirtualRenderer.scrollToLine(line, center)
* - line (Number): The line to go to
* - center (Boolean): Identifies whether you want the cursor centered or not
*
* Scrolls the editor to the `line` indicated.
*
**/
this.scrollToLine = function(line, center) {
var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0});
var offset = pos.top;
if (center)
offset -= this.$size.scrollerHeight / 2;
if (this.$animatedScroll && Math.abs(offset - this.scrollTop) < 10000) {
var _self = this;
var steps = _self.$calcSteps(this.scrollTop, offset);
clearInterval(this.$timer);
this.$timer = setInterval(function() {
_self.session.setScrollTop(steps.shift());
if (!steps.length)
clearInterval(_self.$timer);
}, 10);
}
else {
this.session.setScrollTop(offset);
}
};
/**
@ -1013,18 +1048,6 @@ var VirtualRenderer = function(container, theme) {
// todo: handle horizontal scrolling
};
/**
* VirtualRenderer.screenToTextCoordinates(pageX, pageY) -> Object
* - pageX (Number): The x-coordinate relative to the left edge of the document
* - pageY (Number): The y-coordinate relative to the top edge of the document
*
* Returns the document position, based on the coordinates provided.
*
* #### Returns
*
* The object returned has two properties: `row` and `column`.
*
**/
this.screenToTextCoordinates = function(pageX, pageY) {
var canvasPos = this.scroller.getBoundingClientRect();
@ -1160,7 +1183,7 @@ var VirtualRenderer = function(container, theme) {
return afterLoad(module);
_self._loadTheme(moduleName, function() {
require([theme], function(module) {
require([moduleName], function(module) {
if (_self.$themeValue !== theme)
return;

View file

@ -34,11 +34,16 @@
border-left: 0px;
border-bottom: 1px solid %overwrite%;
}
.%cssClass% .ace_marker-layer .ace_selection {
background: %selection%;
}
.%cssClass%.multiselect .ace_selection.start {
box-shadow: 0 0 3px 0px %background%;
border-radius: 2px;
}
.%cssClass% .ace_marker-layer .ace_step {
background: %step%;
}
@ -55,7 +60,7 @@
.%cssClass% .ace_marker-layer .ace_selected_word {
%selected_word_highlight%
}
.%cssClass% .ace_invisible {
%invisible%
}
@ -72,6 +77,14 @@
%constant%
}
.%cssClass% .ace_constant.ace_character, {
%constant%
}
.%cssClass% .ace_constant.ace_character.ace_escape, {
%constant%
}
.%cssClass% .ace_constant.ace_language {
%constant.language%
}
@ -230,5 +243,5 @@
}
.%cssClass% .ace_collab.ace_user1 {
%collab.user1%
%collab.user1%
}

40
tool/tmtheme.js Normal file → Executable file
View file

@ -8,16 +8,16 @@ function plistToJson(el) {
return $plistParse(el.selectSingleNode("dict"));
}
function $plistParse(el) {
function $plistParse(el) {
if (el.tagName == "dict") {
var dict = {};
var key;
var childNodes = el.childNodes;
for (var i=0, l=childNodes.length; i<l; i++) {
var child = childNodes[i];
if (child.nodeType !== 1)
if (child.nodeType !== 1)
continue;
if (child.tagName == "key") {
key = child.nodeValue;
} else {
@ -34,9 +34,9 @@ function $plistParse(el) {
var childNodes = el.childNodes;
for (var i=0, l=childNodes.length; i<l; i++) {
var child = childNodes[i];
if (child.nodeType !== 1)
if (child.nodeType !== 1)
continue;
arr.push($plistParse(child));
}
return arr;
@ -53,38 +53,39 @@ function parseTheme(themeXml) {
return plistToJson(xml.parseFromString(themeXml).documentElement);
} catch(e) { return; }
}
var supportedScopes = {
"keyword": "keyword",
"keyword.operator": "keyword.operator",
"constant": "constant",
"constant.language": "constant.language",
"constant.library": "constant.library",
"constant.numeric": "constant.numeric",
"constant.character" : "constant.character",
"constant.character.escape" : "constant.character.escape",
"constant.other" : "constant.other",
"support": "support",
"support.function": "support.function",
"support.function.dom": "support.function.dom",
"support.function.firebug": "support.firebug",
"support.function.constant": "support.function.constant",
"support.constant": "support.constant",
"function": "function",
"function.buildin": "function.buildin",
"storage": "storage",
"storage.type": "storage.type",
"invalid": "invalid",
"invalid.illegal": "invalid.illegal",
"invalid.deprecated": "invalid.deprecated",
"string": "string",
"string.regexp": "string.regexp",
"comment": "comment",
"comment.documentation": "comment.doc",
"comment.documentation.tag": "comment.doc.tag",
@ -92,15 +93,16 @@ var supportedScopes = {
"variable": "variable",
"variable.language": "variable.language",
"variable.parameter": "variable.parameter",
"meta": "meta",
"meta": "meta",
"meta.tag.sgml.doctype": "xml_pe",
"meta.tag": "meta.tag",
"meta.tag.form": "meta.tag.form",
"entity.other.attribute-name": "entity.other.attribute-name",
"entity.name.function": "entity.name.function",
"entity.name": "entity.name",
"markup.heading": "markup.heading",
"markup.heading.1": "markup.heading.1",
"markup.heading.2": "markup.heading.2",
@ -109,7 +111,7 @@ var supportedScopes = {
"markup.heading.5": "markup.heading.5",
"markup.heading.6": "markup.heading.6",
"markup.list": "markup.list",
"collab.user1": "collab.user1"
};
@ -148,7 +150,7 @@ function extractStyles(theme) {
if (!colors.fold)
colors.fold = ((colors["entity.name.function"] || colors.keyword).match(/\:([^;]+)/)||[])[1];
if (!colors.selected_word_highlight)
colors.selected_word_highlight = "border: 1px solid " + colors.selection + ";";
@ -211,7 +213,7 @@ function fillTemplate(template, replacements) {
function createTheme(name, styles, cssTemplate, jsTemplate) {
styles.cssClass = "ace-" + hyphenate(name);
var css = fillTemplate(cssTemplate, styles);
css = css.replace(/[^\{\}]+{\s*}/g, "");
return fillTemplate(jsTemplate, {
name: name,