diff --git a/Makefile b/Makefile index 54312a73..579259d1 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY : doc build clean dist -build: +pre_build: git rev-parse HEAD > .git-ref mkdir -p build/src mkdir -p build/demo/kitchen-sink @@ -9,7 +9,8 @@ build: cp -r demo/kitchen-sink/styles.css build/demo/kitchen-sink/styles.css cp demo/kitchen-sink/logo.png build/demo/kitchen-sink/logo.png cp -r doc/site/images build/textarea - + +build: pre_build ./Makefile.dryice.js normal ./Makefile.dryice.js demo ./Makefile.dryice.js bm diff --git a/Makefile.dryice.js b/Makefile.dryice.js index da119177..547c5b1a 100755 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -43,56 +43,61 @@ if (!fs.existsSync) var copy = require('dryice').copy; var ACE_HOME = __dirname; +var BUILD_DIR = "build"; function main(args) { - var target = "minimal"; - if (args.length == 3) { - target = args[2]; - // Check if 'target' contains some allowed value. - if (!/^(normal|bm|demo|minimal)$/.test(target)) - target = "help"; - } + var type = "minimal"; + args = args.map(function(x) { + if (x[0] == "-" && x[1] != "-") + return "-" + x; + return x; + }); + + if (args[2] && (args[2][0] != "-" || args[2].indexOf("h") != -1)) + type = args[2]; - if (target == "help") { - console.log("--- Ace Dryice Build Tool ---"); - console.log(""); - console.log("Options:"); - console.log(" minimal Runs minimal build of Ace"); - console.log(" normal Runs embedded build of Ace"); - console.log(" demo Runs demo build of Ace"); - console.log(" bm Runs bookmarklet build of Ace"); - process.exit(0); - } + var i = args.indexOf("--target"); + if (i != -1 && args[i+1]) + BUILD_DIR = args[i+1]; - var aceProject = { - roots: [ - ACE_HOME + '/lib', - ACE_HOME + '/demo' - ], - textPluginPattern: /^ace\/requirejs\/text!/ - }; - - if (target == "minimal") { - buildAce(aceProject, { - compress: false, - noconflict: false, - suffix: "", - name: "ace" + if (type == "minimal") { + buildAce({ + compress: args.indexOf("-m") != -1, + noconflict: args.indexOf("-nc") != -1 }); + } else if (type == "normal") { + ace(); + } else if (type == "demo") { + demo(); + } else if (type == "bm") { + bookmarklet(); + } else if (type == "full") { + ace(); + demo(); + bookmarklet(); } - if (target == "normal") { - ace(aceProject); - } - else if (target == "demo") { - demo(aceProject); - } - else if (target == "bm") { - bookmarklet(aceProject); - } + + console.log("--- Ace Dryice Build Tool ---"); + console.log(""); + console.log("Options:"); + console.log(" normal Runs embedded build of Ace"); + console.log(" demo Runs demo build of Ace"); + console.log(" bm Runs bookmarklet build of Ace"); + console.log(" full all of above"); + console.log("flags:"); + console.log(" -m minify"); + console.log(" -nc namespace require"); + console.log(" --target ./path path to build folder"); + console.log(""); + if (BUILD_DIR) + console.log(" output generated in " + type + __dirname + "/" + BUILD_DIR) + + process.exit(0); + } -function bookmarklet(aceProject) { - var targetDir = "build/textarea"; +function bookmarklet() { + var targetDir = BUILD_DIR + "/textarea"; copy({ source: "build_support/editor_textarea.html", dest: targetDir + '/editor.html' @@ -102,7 +107,7 @@ function bookmarklet(aceProject) { dest: targetDir + '/style.css' }); - buildAce(aceProject, { + buildAce({ targetDir: targetDir + "/src", ns: "__ace_shadowed__", exportModule: "ace/ext/textarea", @@ -115,38 +120,27 @@ function bookmarklet(aceProject) { }); } -function ace(aceProject) { +function ace() { console.log('# ace ---------'); // uncompressed - buildAce(aceProject, { + buildAce({ compress: false, - noconflict: false, - suffix: "", - name: "ace" + noconflict: false }); - buildAce(aceProject, { + buildAce({ compress: false, - noconflict: true, - suffix: "-noconflict", - name: "ace", - workers: [] + noconflict: true }); // compressed - buildAce(aceProject, { + buildAce({ compress: true, - noconflict: false, - suffix: "-min", - name: "ace", - workers: [] + noconflict: false }); - buildAce(aceProject, { + buildAce({ compress: true, - noconflict: true, - suffix: "-min-noconflict", - name: "ace", - workers: [] + noconflict: true }); console.log('# ace License | Readme | Changelog ---------'); @@ -169,7 +163,7 @@ function ace(aceProject) { }); } -function demo(aceProject) { +function demo() { console.log('# kitchen sink ---------'); var version, ref; @@ -182,14 +176,10 @@ function demo(aceProject) { } var changeComments = function(data) { return (data - .replace("DEVEL-->", "") - .replace("", "") - .replace(" + + + + + +
-
+
+
+
|
@@ -216,8 +226,7 @@
-
-
+
-
+
",
- next : "start"
- }, {
- token : "comment",
- regex : ".+"
- }
+ {
+ token : "comment",
+ regex : ".*?-->",
+ next : "start"
+ }, {
+ token : "comment",
+ regex : ".+"
+ }
],
"htmltag" : [
{
diff --git a/lib/ace/mode/scala_highlight_rules.js b/lib/ace/mode/scala_highlight_rules.js
index 67f8e1b2..c39962db 100644
--- a/lib/ace/mode/scala_highlight_rules.js
+++ b/lib/ace/mode/scala_highlight_rules.js
@@ -75,11 +75,16 @@ var ScalaHighlightRules = function() {
token : "string.regexp",
regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)"
}, {
- token : "string", // single line
- regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
+ token : "string",
+ regex : '"""',
+ next : "tstring"
}, {
- token : "string", // single line
- regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
+ token : "string",
+ regex : '"(?=.)', // " strings can't span multiple lines
+ next : "string"
+ }, {
+ token : "symbol.constant", // single line
+ regex : "'[\\w\\d_]+"
}, {
token : "constant.numeric", // hex
regex : "0[xX][0-9a-fA-F]+\\b"
@@ -131,6 +136,36 @@ var ScalaHighlightRules = function() {
merge : true,
regex : ".+"
}
+ ],
+ "string" : [
+ {
+ token : "escape",
+ regex : '\\\\"',
+ }, {
+ token : "string",
+ merge : true,
+ regex : '"',
+ next : "start"
+ }, {
+ token : "string.invalid",
+ regex : '[^"\\\\]*$',
+ next : "start"
+ }, {
+ token : "string",
+ regex : '[^"\\\\]+',
+ merge : true
+ }
+ ],
+ "tstring" : [
+ {
+ token : "string", // closing comment
+ regex : '"{3,5}',
+ next : "start"
+ }, {
+ token : "string", // comment spanning whole line
+ merge : true,
+ regex : ".+?"
+ }
]
};
diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js
index 49de33e7..094432bf 100644
--- a/lib/ace/mode/text.js
+++ b/lib/ace/mode/text.js
@@ -98,68 +98,6 @@ var Mode = function() {
return null;
};
- this.highlightSelection = function(editor) {
- var session = editor.session;
- if (!session.$selectionOccurrences)
- session.$selectionOccurrences = [];
-
- if (session.$selectionOccurrences.length)
- this.clearSelectionHighlight(editor);
-
- var selection = editor.getSelectionRange();
- if (selection.isEmpty() || selection.isMultiLine())
- return;
-
- var startOuter = selection.start.column - 1;
- var endOuter = selection.end.column + 1;
- var line = session.getLine(selection.start.row);
- var lineCols = line.length;
- var needle = line.substring(Math.max(startOuter, 0),
- Math.min(endOuter, lineCols));
-
- // Make sure the outer characters are not part of the word.
- if ((startOuter >= 0 && /^[\w\d]/.test(needle)) ||
- (endOuter <= lineCols && /[\w\d]$/.test(needle)))
- return;
-
- needle = line.substring(selection.start.column, selection.end.column);
- if (!/^[\w\d]+$/.test(needle))
- return;
-
- var cursor = editor.getCursorPosition();
-
- var newOptions = {
- wrap: true,
- wholeWord: true,
- caseSensitive: true,
- needle: needle
- };
-
- var currentOptions = editor.$search.getOptions();
- editor.$search.set(newOptions);
-
- var ranges = editor.$search.findAll(session);
- ranges.forEach(function(range) {
- if (!range.contains(cursor.row, cursor.column)) {
- var marker = session.addMarker(range, "ace_selected_word", "text");
- session.$selectionOccurrences.push(marker);
- }
- });
-
- editor.$search.set(currentOptions);
- };
-
- this.clearSelectionHighlight = function(editor) {
- if (!editor.session.$selectionOccurrences)
- return;
-
- editor.session.$selectionOccurrences.forEach(function(marker) {
- editor.session.removeMarker(marker);
- });
-
- editor.session.$selectionOccurrences = [];
- };
-
this.createModeDelegates = function (mapping) {
if (!this.$embeds) {
return;
diff --git a/lib/ace/mouse/default_gutter_handler.js b/lib/ace/mouse/default_gutter_handler.js
index 30a5e6f5..fc9b012b 100644
--- a/lib/ace/mouse/default_gutter_handler.js
+++ b/lib/ace/mouse/default_gutter_handler.js
@@ -67,6 +67,7 @@ function GutterHandler(mouseHandler) {
}
mouseHandler.captureMouse(e, "selectByLines");
+ return e.preventDefault();
});
}
diff --git a/lib/ace/mouse/default_handlers.js b/lib/ace/mouse/default_handlers.js
index 48fe88d7..e5568881 100644
--- a/lib/ace/mouse/default_handlers.js
+++ b/lib/ace/mouse/default_handlers.js
@@ -42,16 +42,12 @@ define(function(require, exports, module) {
"use strict";
var dom = require("../lib/dom");
-var BrowserFocus = require("../lib/browser_focus").BrowserFocus;
-
+var useragent = require("../lib/useragent");
var DRAG_OFFSET = 5; // pixels
-
-
function DefaultHandlers(mouseHandler) {
mouseHandler.$clickSelection = null;
- mouseHandler.browserFocus = new BrowserFocus();
var editor = mouseHandler.editor;
editor.setDefaultHandler("mousedown", this.onMouseDown.bind(mouseHandler));
@@ -61,7 +57,7 @@ function DefaultHandlers(mouseHandler) {
editor.setDefaultHandler("mousewheel", this.onScroll.bind(mouseHandler));
var exports = ["select", "startSelect", "drag", "dragEnd", "dragWait",
- "dragWaitEnd", "startDrag"];
+ "dragWaitEnd", "startDrag", "focusWait"];
exports.forEach(function(x) {
mouseHandler[x] = this[x];
@@ -69,44 +65,43 @@ function DefaultHandlers(mouseHandler) {
mouseHandler.selectByLines = this.extendSelectionBy.bind(mouseHandler, "getLineRange");
mouseHandler.selectByWords = this.extendSelectionBy.bind(mouseHandler, "getWordRange");
+
+ mouseHandler.$focusWaitTimout = 250;
}
(function() {
this.onMouseDown = function(ev) {
- this.mousedownEvent = ev;
var inSelection = ev.inSelection();
var pos = ev.getDocumentPosition();
+ this.mousedownEvent = ev;
var editor = this.editor;
var _self = this;
- this.ev = ev
- var selectionRange = editor.getSelectionRange();
- var selectionEmpty = selectionRange.isEmpty();
-
var button = ev.getButton();
if (button !== 0) {
+ var selectionRange = editor.getSelectionRange();
+ var selectionEmpty = selectionRange.isEmpty();
+
if (selectionEmpty) {
editor.moveCursorToPosition(pos);
editor.selection.clearSelection();
}
- // 2: contextmenu, 1: linux paste
- this.moveTextarea = function() {
- editor.textInput.onContextMenu({x: _self.x, y: _self.y});
- };
- this.moveTextareaEnd = editor.textInput.onContextMenuClose;
-
- editor.textInput.onContextMenu({x: this.x, y: this.y}, selectionEmpty);
- this.captureMouse(ev, "moveTextarea");
- return;
+ // 2: contextmenu, 1: linux paste
+ editor.textInput.onContextMenu(ev.domEvent);
+ return ev.stop();
}
// if this click caused the editor to be focused should not clear the
// selection
if (inSelection && !editor.isFocused()) {
editor.focus();
- return;
+ if (this.$focusWaitTimout && !this.$clickSelection) {
+ this.setState("focusWait");
+ this.captureMouse(ev);
+ return ev.preventDefault();
+ }
}
if (!inSelection || this.$clickSelection || ev.getShiftKey()) {
@@ -123,7 +118,8 @@ function DefaultHandlers(mouseHandler) {
}
}
- this.captureMouse(ev)
+ this.captureMouse(ev);
+ return ev.preventDefault();
};
this.startSelect = function(pos) {
@@ -217,6 +213,14 @@ function DefaultHandlers(mouseHandler) {
editor.keyBinding.addKeyboardHandler(this.$dragKeybinding);
};
+ this.focusWait = function() {
+ var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
+ var time = (new Date()).getTime();
+
+ if (distance > DRAG_OFFSET ||time - this.mousedownEvent.time > this.$focusWaitTimout)
+ this.startSelect();
+ };
+
this.dragWait = function() {
var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y);
var time = (new Date()).getTime();
@@ -224,7 +228,7 @@ function DefaultHandlers(mouseHandler) {
if (distance > DRAG_OFFSET) {
this.startSelect();
- } else if ((time - this.mousedownEvent.time) > editor.getDragDelay()) {
+ } else if (time - this.mousedownEvent.time > editor.getDragDelay()) {
this.startDrag()
}
};
diff --git a/lib/ace/mouse/dragdrop.js b/lib/ace/mouse/dragdrop.js
index e69de29b..8fe5cb5e 100644
--- a/lib/ace/mouse/dragdrop.js
+++ b/lib/ace/mouse/dragdrop.js
@@ -0,0 +1,105 @@
+/* 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):
+ *
+ * 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 event = require("../lib/event");
+
+var DragdropHandler = function(mouseHandler) {
+ var editor = mouseHandler.editor;
+ var dragSelectionMarker, x, y;
+ var timerId, range, isBackwards;
+ var dragCursor, counter = 0;
+
+ var mouseTarget = editor.container;
+ event.addListener(mouseTarget, "dragenter", function(e) {console.log(e.type, counter,e.target);
+ counter++;
+ if (!dragSelectionMarker) {
+ range = editor.getSelectionRange();
+ isBackwards = editor.selection.isBackwards();
+ var style = editor.getSelectionStyle();
+ dragSelectionMarker = editor.session.addMarker(range, "ace_selection", style);
+ editor.clearSelection();
+ clearInterval(timerId);
+ timerId = setInterval(onDragInterval, 20);
+ }
+ return event.preventDefault(e);
+ });
+
+ event.addListener(mouseTarget, "dragover", function(e) {
+ x = e.clientX;
+ y = e.clientY;
+ return event.preventDefault(e);
+ });
+
+ var onDragInterval = function() {
+ dragCursor = editor.renderer.screenToTextCoordinates(x, y);
+ editor.moveCursorToPosition(dragCursor);
+ editor.renderer.scrollCursorIntoView();
+ };
+
+ event.addListener(mouseTarget, "dragleave", function(e) {console.log(e.type, counter,e.target);
+ counter--;
+ if (counter > 0)
+ return;
+ console.log(e.type, counter,e.target);
+ clearInterval(timerId);
+ editor.session.removeMarker(dragSelectionMarker);
+ dragSelectionMarker = null;
+ editor.selection.setSelectionRange(range, isBackwards);
+ return event.preventDefault(e);
+ });
+
+ event.addListener(mouseTarget, "drop", function(e) {
+ console.log(e.type, counter,e.target);
+ counter = 0;
+ clearInterval(timerId);
+ editor.session.removeMarker(dragSelectionMarker);
+ dragSelectionMarker = null;
+
+ range.end = editor.session.insert(dragCursor, e.dataTransfer.getData('Text'));
+ range.start = dragCursor;
+ editor.focus();
+ editor.selection.setSelectionRange(range);
+ return event.preventDefault(e);
+ });
+
+};
+
+exports.DragdropHandler = DragdropHandler;
+});
diff --git a/lib/ace/mouse/mouse_handler.js b/lib/ace/mouse/mouse_handler.js
index a85e9672..e1e7a2a1 100644
--- a/lib/ace/mouse/mouse_handler.js
+++ b/lib/ace/mouse/mouse_handler.js
@@ -44,28 +44,24 @@ var event = require("../lib/event");
var DefaultHandlers = require("./default_handlers").DefaultHandlers;
var DefaultGutterHandler = require("./default_gutter_handler").GutterHandler;
var MouseEvent = require("./mouse_event").MouseEvent;
+var DragdropHandler = require("./dragdrop").DragdropHandler;
var MouseHandler = function(editor) {
this.editor = editor;
new DefaultHandlers(this);
new DefaultGutterHandler(this);
+ new DragdropHandler(this);
event.addListener(editor.container, "mousedown", function(e) {
editor.focus();
return event.preventDefault(e);
});
- event.addListener(editor.container, "selectstart", function(e) {
- return event.preventDefault(e);
- });
var mouseTarget = editor.renderer.getMouseEventTarget();
- event.addListener(mouseTarget, "mousedown", this.onMouseEvent.bind(this, "mousedown"));
event.addListener(mouseTarget, "click", this.onMouseEvent.bind(this, "click"));
event.addListener(mouseTarget, "mousemove", this.onMouseMove.bind(this, "mousemove"));
- event.addMultiMouseDownListener(mouseTarget, 0, 2, 500, this.onMouseEvent.bind(this, "dblclick"));
- event.addMultiMouseDownListener(mouseTarget, 0, 3, 600, this.onMouseEvent.bind(this, "tripleclick"));
- event.addMultiMouseDownListener(mouseTarget, 0, 4, 600, this.onMouseEvent.bind(this, "quadclick"));
+ event.addMultiMouseDownListener(mouseTarget, [300, 300, 250], this, "onMouseEvent");
event.addMouseWheelListener(editor.container, this.onMouseWheel.bind(this, "mousewheel"));
var gutterEl = editor.renderer.$gutter;
@@ -129,8 +125,9 @@ var MouseHandler = function(editor) {
this.y = ev.y;
// do not move textarea during selection
- var kt = this.editor.renderer.$keepTextAreaAtCursor;
- this.editor.renderer.$keepTextAreaAtCursor = false;
+ var renderer = this.editor.renderer;
+ if (renderer.$keepTextAreaAtCursor)
+ renderer.$keepTextAreaAtCursor = null;
var self = this;
var onMouseSelection = function(e) {
@@ -142,8 +139,10 @@ var MouseHandler = function(editor) {
clearInterval(timerId);
self[self.state + "End"] && self[self.state + "End"](e);
self.$clickSelection = null;
- self.editor.renderer.$keepTextAreaAtCursor = kt;
- self.editor.renderer.$moveTextAreaToCursor();
+ if (renderer.$keepTextAreaAtCursor == null) {
+ renderer.$keepTextAreaAtCursor = true;
+ renderer.$moveTextAreaToCursor();
+ }
};
var onSelectionInterval = function() {
@@ -152,8 +151,6 @@ var MouseHandler = function(editor) {
event.capture(this.editor.container, onMouseSelection, onMouseSelectionEnd);
var timerId = setInterval(onSelectionInterval, 20);
-
- ev.preventDefault();
};
}).call(MouseHandler.prototype);
diff --git a/lib/ace/multi_select.js b/lib/ace/multi_select.js
index 3560bbb3..9cbc5417 100644
--- a/lib/ace/multi_select.js
+++ b/lib/ace/multi_select.js
@@ -43,7 +43,8 @@ var Range = require("./range").Range;
var Selection = require("./selection").Selection;
var onMouseDown = require("./mouse/multi_select_handler").onMouseDown;
var event = require("./lib/event");
-exports.commands = require("./commands/multi_select_commands");
+var commands = require("./commands/multi_select_commands");
+exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands);
// Todo: session.find or editor.findVolatile that returns range
var Search = require("./search").Search;
@@ -397,7 +398,7 @@ var Editor = require("./editor").Editor;
this.inMultiSelectMode = true;
this.setStyle("multiselect");
- this.keyBinding.addKeyboardHandler(exports.commands.keyboardHandler);
+ this.keyBinding.addKeyboardHandler(commands.keyboardHandler);
this.commands.on("exec", this.$onMultiSelectExec);
this.renderer.updateCursor();
@@ -410,7 +411,7 @@ var Editor = require("./editor").Editor;
this.inMultiSelectMode = false;
this.unsetStyle("multiselect");
- this.keyBinding.removeKeyboardHandler(exports.commands.keyboardHandler);
+ this.keyBinding.removeKeyboardHandler(commands.keyboardHandler);
this.commands.removeEventListener("exec", this.$onMultiSelectExec);
this.renderer.updateCursor();
@@ -420,6 +421,8 @@ var Editor = require("./editor").Editor;
this.$onMultiSelectExec = function(e) {
var command = e.command;
var editor = e.editor;
+ if (!editor.multiSelect)
+ return;
if (!command.multiSelectAction) {
command.exec(editor, e.args || {});
editor.multiSelect.addRange(editor.multiSelect.toOrientedRange());
@@ -724,7 +727,7 @@ function MultiSelect(editor) {
editor.on("changeSession", exports.onSessionChange.bind(editor));
editor.on("mousedown", onMouseDown);
- editor.commands.addCommands(exports.commands.defaultCommands);
+ editor.commands.addCommands(commands.defaultCommands);
addAltCursorListeners(editor);
}
diff --git a/lib/ace/range_list.js b/lib/ace/range_list.js
index 185ca5a6..8f6f34f6 100644
--- a/lib/ace/range_list.js
+++ b/lib/ace/range_list.js
@@ -196,10 +196,9 @@ var RangeList = function() {
var lineDif = endRow - startRow;
var colDiff = -start.column + end.column;
-
var ranges = this.ranges;
- for (var i=0, n = ranges.length; i < n; i++) {
+ for (var i = 0, n = ranges.length; i < n; i++) {
var r = ranges[i];
if (r.end.row < startRow)
continue;
diff --git a/lib/ace/search.js b/lib/ace/search.js
index dedcadea..c03391e2 100644
--- a/lib/ace/search.js
+++ b/lib/ace/search.js
@@ -54,35 +54,25 @@ var Range = require("./range").Range;
/**
* new Search()
*
- * Creates a new `Search` object. The search options contain the following defaults:
+ * Creates a new `Search` object. The following search options are avaliable:
*
- * * `needle`: `""`
- * * `backwards`: `false`
- * * `wrap`: `false`
- * * `caseSensitive`: `false`
- * * `wholeWord`: `false`
- * * `scope`: `ALL`
- * * `regExp`: `false`
+ * * needle: string or regular expression
+ * * backwards: false
+ * * wrap: false
+ * * caseSensitive: false
+ * * wholeWord: false
+ * * range: Range or null for whole document
+ * * regExp: false
+ * * start: Range or position
+ * * skipCurrent: false
*
**/
var Search = function() {
- this.$options = {
- needle: "",
- backwards: false,
- wrap: false,
- caseSensitive: false,
- wholeWord: false,
- scope: Search.ALL,
- regExp: false
- };
+ this.$options = {};
};
-Search.ALL = 1;
-Search.SELECTION = 2;
-
(function() {
-
/**
* Search.set(options) -> Search
* - options (Object): An object containing all the new search properties
@@ -105,6 +95,9 @@ Search.SELECTION = 2;
return lang.copyObject(this.$options);
};
+ this.setOptions = function(options) {
+ this.$options = options;
+ };
/**
* Search.find(session) -> Range
* - session (EditSession): The session to search with
@@ -113,17 +106,18 @@ Search.SELECTION = 2;
*
**/
this.find = function(session) {
- if (!this.$options.needle)
- return null;
-
- var iterator = this.$matchIterator(session);
+ var iterator = this.$matchIterator(session, this.$options);
if (!iterator)
return false;
var firstRange = null;
- iterator.forEach(function(range) {
- firstRange = range;
+ iterator.forEach(function(range, row, offset) {
+ if (!range.start) {
+ var column = range.offset + (offset || 0);
+ firstRange = new Range(row, column, row, column+range.length);
+ } else
+ firstRange = range;
return true;
});
@@ -141,23 +135,53 @@ Search.SELECTION = 2;
var options = this.$options;
if (!options.needle)
return [];
+ this.$assembleRegExp(options);
- var iterator = this.$matchIterator(session);
-
- if (!iterator)
- return false;
-
- var ignoreCursor = !options.start && options.wrap && options.scope == Search.ALL;
- if (ignoreCursor)
- options.start = {row: 0, column: 0};
+ if (options.range) {
+ var range = options.range;
+ var lines = session.getLines(range.start.row, range.end.row);
+ } else
+ var lines = session.doc.getAllLines();
var ranges = [];
- iterator.forEach(function(range) {
- ranges.push(range);
- });
+ var re = options.re;
+ if (options.$isMultiLine) {
+ var len = re.length;
+ var maxRow = lines.length - len;
+ for (var row = re.offset || 0; row < maxRow; row++) {
+ for (var j = 0; j < re.length; j++)
+ if (lines[row + j].search(re[j]) == -1)
+ break;
- if (ignoreCursor)
- options.start = null;
+ var startIndex = lines[row + j].match(re[0])[0].length;
+ var endIndex = line.match(re[len - 1])[0].length;
+
+ ranges.push(new Range(
+ row, startLine.length - startIndex,
+ row + len - 1, endIndex
+ ));
+ }
+ } else {
+ for (var i = 0; i < lines.length; i++) {
+ var matches = lang.getMatchOffsets(lines[i], re);
+ for (var j = 0; j < matches.length; j++) {
+ var match = matches[j];
+ ranges.push(new Range(i, match.offset, i, match.offset + match.length));
+ };
+ }
+ }
+
+ if (options.range) {
+ var startColumn = range.start.column;
+ var endColumn = range.start.column;
+ var i = 0, j = ranges.length - 1;
+ while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row)
+ i++;
+
+ while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row)
+ j--;
+ return ranges.slice(i, j + 1);
+ }
return ranges;
};
@@ -173,252 +197,195 @@ Search.SELECTION = 2;
*
**/
this.replace = function(input, replacement) {
- if (!this.$options.regExp)
- return input == this.$options.needle ? replacement : null;
-
- var re = this.$assembleRegExp();
+ var options = this.$options;
+
+ var re = this.$assembleRegExp(options);
+ if (options.$isMultiLine)
+ return replacement;
+
if (!re)
return;
var match = re.exec(input);
- if (match && match[0].length == input.length) {
- return input.replace(re, replacement);
- }
- else {
+ if (!match || match[0].length != input.length)
return null;
+
+ replacement = input.replace(re, replacement)
+ if (options.preserveCase) {
+ replacement = replacement.split("");
+ for (var i = Math.min(input.length, input.length); i--; ) {
+ var ch = input[i];
+ if (ch && ch.toLowerCase() != ch)
+ replacement[i] = replacement[i].toUpperCase();
+ else
+ replacement[i] = replacement[i].toLowerCase();
+ }
+ replacement = replacement.join("");
}
+
+ return replacement;
};
/** internal, hide
* Search.$matchIterator(session) -> String | Boolean
* - session (EditSession): The session to search with
*
- *
- *
**/
- this.$matchIterator = function(session) {
- var re = this.$assembleRegExp();
+ this.$matchIterator = function(session, options) {
+ var re = this.$assembleRegExp(options);
if (!re)
return false;
- var self = this, callback, backwards = this.$options.backwards;
+ var self = this, callback, backwards = options.backwards;
- if (this.$options.$isMultiLine) {
- var matchIterator = function(line, startIndex, row) {
- var startLine = line;
- if (startIndex)
- line = line.substring(startIndex);
-
- var len = re.length;
- var part = re[0];
- if (line.slice(-part.length) != part)
+ if (options.$isMultiLine) {
+ var len = re.length;
+ var matchIterator = function(line, row, offset) {
+ var startIndex = line.search(re[0]);
+ if (startIndex == -1)
return;
-
- for (var i = 1; i < len - 1; i++)
- if (re[i] != session.getLine(row + i))
+ for (var i = 1; i < len; i++) {
+ line = session.getLine(row + i);
+ if (line.search(re[i]) == -1)
return;
+ }
- part = re[len - 1];
- if (session.getLine(row + len - 1).slice(0, part.length) != part)
- return;
+ var endIndex = line.match(re[len - 1])[0].length;
+
+ var range = new Range(row, startIndex, row + len - 1, endIndex);
+ if (re.offset == 1) {
+ range.start.row--;
+ range.start.column = Number.MAX_VALUE;
+ } else if (offset)
+ range.start.column += offset;
- var range = new Range(
- row, startLine.length - re[0].length,
- row + len - 1, re[len - 1].length
- );
if (callback(range))
return true;
}
} else if (backwards) {
- var matchIterator = function(line, startIndex, row) {
- if (startIndex)
- line = line.substring(startIndex);
-
- var matches = [];
-
- line.replace(re, function(str) {
- var offset = arguments[arguments.length-2];
- matches.push({
- str: str,
- offset: startIndex + offset
- });
- return str;
- });
-
- for (var i=matches.length-1; i>= 0; i--) {
- var match = matches[i];
- var range = self.$rangeFromMatch(row, match.offset, match.str.length);
- if (callback(range))
+ var matchIterator = function(line, row, startIndex) {
+ var matches = lang.getMatchOffsets(line, re);
+ for (var i = matches.length-1; i >= 0; i--)
+ if (callback(matches[i], row, startIndex))
return true;
- }
}
} else {
- var matchIterator = function(line, startIndex, row) {
- if (startIndex)
- line = line.substring(startIndex);
-
- var matches = [];
-
- line.replace(re, function(str) {
- var offset = arguments[arguments.length-2];
- matches.push({
- str: str,
- offset: startIndex + offset
- });
- return str;
- });
-
- for (var i=0; i |