From c4cb541414f58ebb180b944c43ee994b7777fbbe Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 24 May 2012 23:29:25 +0400 Subject: [PATCH 01/40] fix doc/wiki --- doc/wiki | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/wiki b/doc/wiki index 8bd16ba2..d93670b4 160000 --- a/doc/wiki +++ b/doc/wiki @@ -1 +1 @@ -Subproject commit 8bd16ba2eda6a1b0c6791f37d0803296ae37840f +Subproject commit d93670b47d776987b38bb2c31777c4e488338fac From 69c8f6615d2e00d53f17cab9dd14e8f019e8c1ed Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Thu, 10 May 2012 11:47:32 -0700 Subject: [PATCH 02/40] Updates for ace performance related to new searchinfiles work --- lib/ace/document.js | 7 ++++++- lib/ace/edit_session/folding.js | 9 ++++++++- lib/ace/worker/worker.js | 7 ++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 99afe895..1c89fcf1 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -327,8 +327,13 @@ var Document = function(text) { return {row: row, column: 0}; var args = [row, 0]; - args.push.apply(args, lines); + var step = 100000; + var l = Math.ceil(lines.length / step); + for (var tlines, i = 0; i < l; i++) { + tlines = lines.slice(i * step, step); + args.push.apply(args, tlines); this.$lines.splice.apply(this.$lines, args); + } var range = new Range(row, 0, row + lines.length, 0); var delta = { diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 3a113c84..46f9583c 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -748,7 +748,14 @@ function Folding() { } else { var args = Array(len + 1); args.unshift(firstRow, 1); - this.foldWidgets.splice.apply(this.foldWidgets, args); + + var step = 100000; + var l = Math.ceil(args.length / step); + for (var targs, i = 0; i < l; i++) { + targs = args.slice(i * step, step); + this.foldWidgets.splice.apply(this.foldWidgets, targs); + } + } }; diff --git a/lib/ace/worker/worker.js b/lib/ace/worker/worker.js index 295f90b3..04832b6a 100644 --- a/lib/ace/worker/worker.js +++ b/lib/ace/worker/worker.js @@ -123,7 +123,12 @@ var sender; onmessage = function(e) { var msg = e.data; if (msg.command) { - main[msg.command].apply(main, msg.args); + var step = 100000; + var l = Math.ceil(msg.args.length / step); + for (var targs, i = 0; i < l; i++) { + targs = msg.args.slice(i * step, step); + main[msg.command].apply(main, targs); + } } else if (msg.init) { initBaseUrls(msg.tlns); From 93a560885b8d2529a67f740316ec76efd0a8c41a Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Thu, 10 May 2012 15:25:31 -0700 Subject: [PATCH 03/40] Generalize chunking --- lib/ace/edit_session/folding.js | 10 ++-------- lib/ace/lib/lang.js | 15 +++++++++++++++ lib/ace/worker/worker.js | 9 ++------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 46f9583c..1789ef1e 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -43,7 +43,7 @@ var Range = require("../range").Range; var FoldLine = require("./fold_line").FoldLine; var Fold = require("./fold").Fold; var TokenIterator = require("../token_iterator").TokenIterator; - +var lang = require("../lib/lang"); function Folding() { /* * Looks up a fold at a given row/column. Possible values for side: @@ -749,13 +749,7 @@ function Folding() { var args = Array(len + 1); args.unshift(firstRow, 1); - var step = 100000; - var l = Math.ceil(args.length / step); - for (var targs, i = 0; i < l; i++) { - targs = args.slice(i * step, step); - this.foldWidgets.splice.apply(this.foldWidgets, targs); - } - + this.foldWidgets = lang.chunkLines(args, this.foldWidgets); } }; diff --git a/lib/ace/lib/lang.js b/lib/ace/lib/lang.js index c8b7afa3..bc118b2c 100644 --- a/lib/ace/lib/lang.js +++ b/lib/ace/lib/lang.js @@ -147,4 +147,19 @@ exports.deferredCall = function(fcn) { return deferred; }; + +exports.chunkLines = function(args, thingToSplice, thingtoApply) { + if (thingtoApply === undefined) + thingtoApply = thingToSplice; + + var step = 100000; + var l = Math.ceil(args.length / step); + for (var targs, i = 0; i < l; i++) { + targs = args.slice(i * step, step); + thingToSplice.slice.apply(thingtoApply, targs); + } + + return thingToSplice; +}; + }); diff --git a/lib/ace/worker/worker.js b/lib/ace/worker/worker.js index 04832b6a..ed2f771d 100644 --- a/lib/ace/worker/worker.js +++ b/lib/ace/worker/worker.js @@ -1,5 +1,5 @@ "no use strict"; - +var lang = require("../lib/lang"); var console = { log: function(msg) { postMessage({type: "log", data: msg}); @@ -123,12 +123,7 @@ var sender; onmessage = function(e) { var msg = e.data; if (msg.command) { - var step = 100000; - var l = Math.ceil(msg.args.length / step); - for (var targs, i = 0; i < l; i++) { - targs = msg.args.slice(i * step, step); - main[msg.command].apply(main, targs); - } + main[msg.command] = lang.chunkLines(msg.args, main[msg.command], main); } else if (msg.init) { initBaseUrls(msg.tlns); From 84e3687e0133cbe0918aba86c02bea327ad9dd59 Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Thu, 10 May 2012 15:53:29 -0700 Subject: [PATCH 04/40] Generalize for document --- lib/ace/document.js | 11 ++--------- lib/ace/lib/lang.js | 13 +++++++++---- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 1c89fcf1..8f1a9f08 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -42,7 +42,7 @@ var oop = require("./lib/oop"); var EventEmitter = require("./lib/event_emitter").EventEmitter; var Range = require("./range").Range; var Anchor = require("./anchor").Anchor; - +var lang = require("./lib/lang"); /** * class Document * @@ -327,14 +327,7 @@ var Document = function(text) { return {row: row, column: 0}; var args = [row, 0]; - var step = 100000; - var l = Math.ceil(lines.length / step); - for (var tlines, i = 0; i < l; i++) { - tlines = lines.slice(i * step, step); - args.push.apply(args, tlines); - this.$lines.splice.apply(this.$lines, args); - } - + this.$lines = lang.chunkLines(lines, this.$lines, args, true); var range = new Range(row, 0, row + lines.length, 0); var delta = { action: "insertLines", diff --git a/lib/ace/lib/lang.js b/lib/ace/lib/lang.js index bc118b2c..8477b65c 100644 --- a/lib/ace/lib/lang.js +++ b/lib/ace/lib/lang.js @@ -147,16 +147,21 @@ exports.deferredCall = function(fcn) { return deferred; }; - -exports.chunkLines = function(args, thingToSplice, thingtoApply) { +// because of Document, this is confusing as shit +exports.chunkLines = function(args, thingToSplice, thingtoApply, isDocument) { if (thingtoApply === undefined) thingtoApply = thingToSplice; - + var step = 100000; var l = Math.ceil(args.length / step); for (var targs, i = 0; i < l; i++) { targs = args.slice(i * step, step); - thingToSplice.slice.apply(thingtoApply, targs); + if (isDocument) { + thingtoApply.push.apply(thingtoApply, targs); + thingToSplice.splice.apply(thingToSplice, thingtoApply); + } + else + thingToSplice.slice.apply(thingtoApply, targs); } return thingToSplice; From d2163a7016d06c27ec810bad208d40d5e44434ef Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Fri, 11 May 2012 15:47:03 -0700 Subject: [PATCH 05/40] Update highlighter --- lib/ace/mode/c9search_highlight_rules.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ace/mode/c9search_highlight_rules.js b/lib/ace/mode/c9search_highlight_rules.js index 0555963a..c16b48c0 100644 --- a/lib/ace/mode/c9search_highlight_rules.js +++ b/lib/ace/mode/c9search_highlight_rules.js @@ -47,13 +47,13 @@ var C9SearchHighlightRules = function() { // regexps are ordered -> the first match is used this.$rules = { "start" : [ + { + token : ["constant.numeric", "text", "text"], + regex : "(^\\s+[0-9]+)(:\\s*)(.+)" + }, { token : ["string", "text"], // single line regex : "(.+)(:$)" - }, - { - token : ["constant.numeric", "text"], - regex : "(^\\s*[0-9]+)(:\\s*)" } ] }; From 505b1fc3c63dee7e63fdadfe4f5143e61142d9a6 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 22 May 2012 23:15:34 +0400 Subject: [PATCH 06/40] fix foldwidgets getting out of sync with document --- lib/ace/document.js | 13 ++++++++++--- lib/ace/edit_session/folding.js | 5 ++--- lib/ace/lib/lang.js | 20 -------------------- lib/ace/worker/worker.js | 4 ++-- 4 files changed, 14 insertions(+), 28 deletions(-) diff --git a/lib/ace/document.js b/lib/ace/document.js index 8f1a9f08..b8379854 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -42,7 +42,7 @@ var oop = require("./lib/oop"); var EventEmitter = require("./lib/event_emitter").EventEmitter; var Range = require("./range").Range; var Anchor = require("./anchor").Anchor; -var lang = require("./lib/lang"); + /** * class Document * @@ -326,8 +326,15 @@ var Document = function(text) { if (lines.length == 0) return {row: row, column: 0}; + if (lines.length > 0xFFFF) { + var end = this.insertLines(row, lines.slice(0xFFFF)); + lines = lines.slice(0, 0xFFFF); + } + var args = [row, 0]; - this.$lines = lang.chunkLines(lines, this.$lines, args, true); + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + var range = new Range(row, 0, row + lines.length, 0); var delta = { action: "insertLines", @@ -335,7 +342,7 @@ var Document = function(text) { lines: lines }; this._emit("change", { data: delta }); - return range.end; + return end || range.end; }; /** diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 1789ef1e..3a113c84 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -43,7 +43,7 @@ var Range = require("../range").Range; var FoldLine = require("./fold_line").FoldLine; var Fold = require("./fold").Fold; var TokenIterator = require("../token_iterator").TokenIterator; -var lang = require("../lib/lang"); + function Folding() { /* * Looks up a fold at a given row/column. Possible values for side: @@ -748,8 +748,7 @@ function Folding() { } else { var args = Array(len + 1); args.unshift(firstRow, 1); - - this.foldWidgets = lang.chunkLines(args, this.foldWidgets); + this.foldWidgets.splice.apply(this.foldWidgets, args); } }; diff --git a/lib/ace/lib/lang.js b/lib/ace/lib/lang.js index 8477b65c..c8b7afa3 100644 --- a/lib/ace/lib/lang.js +++ b/lib/ace/lib/lang.js @@ -147,24 +147,4 @@ exports.deferredCall = function(fcn) { return deferred; }; -// because of Document, this is confusing as shit -exports.chunkLines = function(args, thingToSplice, thingtoApply, isDocument) { - if (thingtoApply === undefined) - thingtoApply = thingToSplice; - - var step = 100000; - var l = Math.ceil(args.length / step); - for (var targs, i = 0; i < l; i++) { - targs = args.slice(i * step, step); - if (isDocument) { - thingtoApply.push.apply(thingtoApply, targs); - thingToSplice.splice.apply(thingToSplice, thingtoApply); - } - else - thingToSplice.slice.apply(thingtoApply, targs); - } - - return thingToSplice; -}; - }); diff --git a/lib/ace/worker/worker.js b/lib/ace/worker/worker.js index ed2f771d..295f90b3 100644 --- a/lib/ace/worker/worker.js +++ b/lib/ace/worker/worker.js @@ -1,5 +1,5 @@ "no use strict"; -var lang = require("../lib/lang"); + var console = { log: function(msg) { postMessage({type: "log", data: msg}); @@ -123,7 +123,7 @@ var sender; onmessage = function(e) { var msg = e.data; if (msg.command) { - main[msg.command] = lang.chunkLines(msg.args, main[msg.command], main); + main[msg.command].apply(main, msg.args); } else if (msg.init) { initBaseUrls(msg.tlns); From 1de8c413c6cc5dd5d272c139c84bfcf9dcd722be Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 25 May 2012 00:00:10 +0400 Subject: [PATCH 07/40] fix textinput and contextmenu --- lib/ace/css/editor.css | 20 +++--- lib/ace/keyboard/textinput.js | 115 +++++++++++++++++------------- lib/ace/mouse/default_handlers.js | 19 ++--- lib/ace/mouse/mouse_handler.js | 3 - lib/ace/virtual_renderer.js | 54 +++++++------- 5 files changed, 110 insertions(+), 101 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index b38dc453..aad4d2bf 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -18,13 +18,6 @@ cursor: text; } -.ace_composition { - position: absolute; - background: #555; - color: #DDD; - z-index: 4; -} - .ace_gutter { position: absolute; overflow : hidden; @@ -95,8 +88,8 @@ height: 100%; } -.ace_editor textarea { - position: fixed; +.ace_editor > textarea { + position: absolute; z-index: 0; width: 0.5em; height: 1em; @@ -110,6 +103,15 @@ overflow: hidden; } +.ace_editor > textarea.ace_composition { + background: #fff; + color: #000; + z-index: 1000; + opacity: 1; + border: solid lightgray 1px; + margin: -1px +} + .ace_layer { z-index: 1; position: absolute; diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index e053e33f..d39b13e3 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -45,18 +45,22 @@ var useragent = require("../lib/useragent"); var dom = require("../lib/dom"); var TextInput = function(parentNode, host) { - var text = dom.createElement("textarea"); + /*/ debug + text.style.opacity = 1 + text.style.background = "rgba(0, 250, 0, 0.3)" + text.style.outline = "rgba(0, 250, 0, 0.8) solid 1px" + text.style.outlineOffset = "3px" + /**/ if (useragent.isTouchPad) text.setAttribute("x-palm-disable-auto-cap", true); text.setAttribute("wrap", "off"); - text.style.left = "-10000px"; - text.style.position = "fixed"; + text.style.top = "-2em"; parentNode.insertBefore(text, parentNode.firstChild); - var PLACEHOLDER = String.fromCharCode(0); + var PLACEHOLDER = useragent.isIE ? "\x01" : "\x01"; sendText(); var inCompostion = false; @@ -64,9 +68,14 @@ var TextInput = function(parentNode, host) { var pasted = false; var tempStyle = ''; - function select() { + function reset(full) { try { - text.select(); + if (full) { + text.value = PLACEHOLDER; + text.selectionStart = 0; + text.selectionEnd = 1; + } else + text.select(); } catch (e) {} } @@ -87,11 +96,6 @@ var TextInput = function(parentNode, host) { else host.onTextInput(value); } - - // If editor is no longer focused we quit immediately, since - // it means that something else is in charge now. - if (!isFocused()) - return false; } } @@ -99,19 +103,19 @@ var TextInput = function(parentNode, host) { pasted = false; // Safari doesn't fire copy events if no text is selected - text.value = PLACEHOLDER; - select(); + reset(true); } var onTextInput = function(e) { + if (!inCompostion) + sendText(e.data); setTimeout(function () { if (!inCompostion) - sendText(e.data); + reset(true); }, 0); }; - + var onPropertyChange = function(e) { - if (useragent.isOldIE && text.value.charCodeAt(0) > 128) return; setTimeout(function() { if (!inCompostion) sendText(); @@ -121,7 +125,7 @@ var TextInput = function(parentNode, host) { var onCompositionStart = function(e) { inCompostion = true; host.onCompositionStart(); - if (!useragent.isGecko) setTimeout(onCompositionUpdate, 0); + setTimeout(onCompositionUpdate, 0); }; var onCompositionUpdate = function() { @@ -141,12 +145,12 @@ var TextInput = function(parentNode, host) { text.value = copyText; else e.preventDefault(); - select(); + reset(); setTimeout(function () { sendText(); }, 0); }; - + var onCut = function(e) { copied = true; var copyText = host.getCopyText(); @@ -155,31 +159,15 @@ var TextInput = function(parentNode, host) { host.onCut(); } else e.preventDefault(); - select(); + reset(); setTimeout(function () { sendText(); }, 0); }; event.addCommandKeyListener(text, host.onCommandKey.bind(host)); + event.addListener(text, "input", useragent.isIE ? onPropertyChange : onTextInput); - if (useragent.isOldIE) { - var keytable = { 13:1, 27:1 }; - event.addListener(text, "keyup", function (e) { - if (inCompostion && (!text.value || keytable[e.keyCode])) - setTimeout(onCompositionEnd, 0); - if ((text.value.charCodeAt(0)|0) < 129) { - return; - } - inCompostion ? onCompositionUpdate() : onCompositionStart(); - }); - } - - if ("onpropertychange" in text && !("oninput" in text)) - event.addListener(text, "propertychange", onPropertyChange); - else - event.addListener(text, "input", onTextInput); - event.addListener(text, "paste", function(e) { // Mark that the next input text comes from past. pasted = true; @@ -198,6 +186,8 @@ var TextInput = function(parentNode, host) { if ("onbeforecopy" in text && typeof clipboardData !== "undefined") { event.addListener(text, "beforecopy", function(e) { + if (tempStyle) + return; // without this text is copied when contextmenu is shown var copyText = host.getCopyText(); if (copyText) clipboardData.setData("Text", copyText); @@ -214,6 +204,7 @@ var TextInput = function(parentNode, host) { event.preventDefault(e); } }); + event.addListener(text, "cut", onCut); // for ie9 context menu } else if (useragent.isOpera) { event.addListener(parentNode, "keydown", function(e) { @@ -251,12 +242,12 @@ var TextInput = function(parentNode, host) { event.addListener(text, "focus", function() { host.onFocus(); - select(); + reset(); }); this.focus = function() { host.onFocus(); - select(); + reset(); text.focus(); }; @@ -273,28 +264,50 @@ var TextInput = function(parentNode, host) { return text; }; - this.onContextMenu = function(mousePos, isEmpty){ - if (mousePos) { - if (!tempStyle) - tempStyle = text.style.cssText; - - text.style.cssText = - 'position:fixed; z-index:1000;' + - 'left:' + (mousePos.x - 2) + 'px; top:' + (mousePos.y - 2) + 'px;'; - } - if (isEmpty) - text.value=''; + this.onContextMenu = function(e) { + if (!tempStyle) + tempStyle = text.style.cssText; + + text.style.cssText = + "position:fixed; z-index:100000;" + //"background:rgba(250, 0, 0, 0.3); opacity:1;" + + "left:" + (e.clientX - 2) + "px; top:" + (e.clientY - 2) + "px;"; + + if (host.selection.isEmpty()) + text.value = ""; + + if (e.type != "mousedown") + return; + + if (host.renderer.$keepTextAreaAtCursor) + host.renderer.$keepTextAreaAtCursor = null; + + event.capture(host.container, function(e) { + text.style.left = e.clientX - 2 + "px"; + text.style.top = e.clientY - 2 + "px"; + }, onContextMenuClose); }; - this.onContextMenuClose = function(){ + function onContextMenuClose() { setTimeout(function () { if (tempStyle) { text.style.cssText = tempStyle; tempStyle = ''; } sendText(); + if (host.renderer.$keepTextAreaAtCursor == null) { + host.renderer.$keepTextAreaAtCursor = true; + host.renderer.$moveTextAreaToCursor(); + } }, 0); }; + this.onContextMenuClose = onContextMenuClose; + + // firefox fires contextmenu event after opening it + if (!useragent.isGecko) + event.addListener(text, "contextmenu", function(e) { + host.textInput.onContextMenu(e); + onContextMenuClose() + }); }; exports.TextInput = TextInput; diff --git a/lib/ace/mouse/default_handlers.js b/lib/ace/mouse/default_handlers.js index 48fe88d7..8c804f2b 100644 --- a/lib/ace/mouse/default_handlers.js +++ b/lib/ace/mouse/default_handlers.js @@ -80,26 +80,19 @@ function DefaultHandlers(mouseHandler) { 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 diff --git a/lib/ace/mouse/mouse_handler.js b/lib/ace/mouse/mouse_handler.js index a85e9672..f7dbee99 100644 --- a/lib/ace/mouse/mouse_handler.js +++ b/lib/ace/mouse/mouse_handler.js @@ -55,9 +55,6 @@ var MouseHandler = function(editor) { 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")); diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 363f3cd8..190471fa 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -533,13 +533,23 @@ var VirtualRenderer = function(container, theme) { var posLeft = this.$cursorLayer.$pixelPos.left; posTop -= this.layerConfig.offset; - if (posTop < 0 || posTop > this.layerConfig.height) + if (posTop < 0 || posTop > this.layerConfig.height - this.lineHeight) return; - posLeft += (this.showGutter ? this.$gutterLayer.gutterWidth : 0) - this.scrollLeft; - var bounds = this.container.getBoundingClientRect(); - this.textarea.style.left = (bounds.left + posLeft) + "px"; - this.textarea.style.top = (bounds.top + posTop) + "px"; + var w = this.characterWidth; + if (this.$composition) + w += this.textarea.scrollWidth; + posLeft -= this.scrollLeft; + if (posLeft > this.$size.scrollerWidth - w) + posLeft = this.$size.scrollerWidth - w; + + if (this.showGutter) + posLeft += this.$gutterLayer.gutterWidth; + + this.textarea.style.height = this.lineHeight + "px"; + this.textarea.style.width = w + "px"; + this.textarea.style.left = posLeft + "px"; + this.textarea.style.top = posTop - 1 + "px"; }; /** @@ -1211,21 +1221,16 @@ var VirtualRenderer = function(container, theme) { * **/ this.showComposition = function(position) { - if (!this.$composition) { - this.$composition = dom.createElement("div"); - this.$composition.className = "ace_composition"; - this.content.appendChild(this.$composition); - } + if (!this.$composition) + this.$composition = { + keepTextAreaAtCursor: this.$keepTextAreaAtCursor, + cssText: this.textarea.style.cssText + }; - this.$composition.innerHTML = " "; - - var pos = this.$cursorLayer.getPixelPosition(); - var style = this.$composition.style; - style.top = pos.top + "px"; - style.left = (pos.left + this.$padding) + "px"; - style.height = this.lineHeight + "px"; - - this.hideCursor(); + this.$keepTextAreaAtCursor = true; + dom.addCssClass(this.textarea, "ace_composition"); + this.textarea.style.cssText = ""; + this.$moveTextAreaToCursor(); }; /** @@ -1235,7 +1240,7 @@ var VirtualRenderer = function(container, theme) { * Sets the inner text of the current composition to `text`. **/ this.setCompositionText = function(text) { - dom.setInnerText(this.$composition, text); + this.$moveTextAreaToCursor(); }; /** @@ -1244,14 +1249,13 @@ var VirtualRenderer = function(container, theme) { * Hides the current composition. **/ this.hideComposition = function() { - this.showCursor(); - if (!this.$composition) return; - var style = this.$composition.style; - style.top = "-10000px"; - style.left = "-10000px"; + dom.removeCssClass(this.textarea, "ace_composition"); + this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor; + this.textarea.style.cssText = this.$composition.cssText; + this.$composition = null; }; this._loadTheme = function(name, callback) { From ac5e033149b054a1b2cfb7eb4b5935ba4e3f7939 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 25 May 2012 10:33:02 +0400 Subject: [PATCH 08/40] add comment --- lib/ace/document.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ace/document.js b/lib/ace/document.js index b8379854..3cae6399 100644 --- a/lib/ace/document.js +++ b/lib/ace/document.js @@ -326,6 +326,8 @@ var Document = function(text) { if (lines.length == 0) return {row: row, column: 0}; + // apply doesn't work for big arrays (smallest threshold is on safari 0xFFFF) + // to circumvent that we have to break huge inserts into smaller chunks here if (lines.length > 0xFFFF) { var end = this.insertLines(row, lines.slice(0xFFFF)); lines = lines.slice(0, 0xFFFF); From 0ca8f694c68e39bda325856e3a18f80ebe9d7f89 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 11 May 2012 12:02:27 +0400 Subject: [PATCH 09/40] remove redundant full redraw this was needed when lines had width in style attribute --- lib/ace/virtual_renderer.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 190471fa..d774383e 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -810,10 +810,6 @@ var VirtualRenderer = function(container, theme) { var layerConfig = this.layerConfig; - // if the update changes the width of the document do a full redraw - if (layerConfig.width != this.$getLongestLine()) - return this.$textLayer.update(layerConfig); - if (firstRow > layerConfig.lastRow + 1) { return; } if (lastRow < layerConfig.firstRow) { return; } From 156d7c5c8f848248f84b005f1aec2f40ae1c6d8a Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 11 May 2012 13:00:33 +0400 Subject: [PATCH 10/40] multiline clojure strings (fix #641) --- lib/ace/mode/clojure_highlight_rules.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/ace/mode/clojure_highlight_rules.js b/lib/ace/mode/clojure_highlight_rules.js index d5e8ed88..0a42e0dc 100644 --- a/lib/ace/mode/clojure_highlight_rules.js +++ b/lib/ace/mode/clojure_highlight_rules.js @@ -191,6 +191,10 @@ var ClojureHighlightRules = function() { }, { token : "string", // single line regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + }, { + token : "string", // multi line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?$', + next: "string" }, { token : "string", // symbol regex : "[:](?:[a-zA-Z]|\\d)+" @@ -210,6 +214,17 @@ var ClojureHighlightRules = function() { merge : true, regex : ".+" } + ], + "string" : [ + { + token : "string", + merge : true, + regex : "\\\\." + }, { + token : "string", + regex : '[^"\\\\]*?"', + next : "start" + } ] }; }; From 1def90083464a396f56650373d6e2a690c25ac11 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 12 May 2012 11:22:01 +0400 Subject: [PATCH 11/40] animated scrolling could leave cursor off screen --- lib/ace/virtual_renderer.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index d774383e..d264c7cf 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -1068,7 +1068,7 @@ var VirtualRenderer = function(container, theme) { var _self = this; var steps = _self.$calcSteps(fromValue, toValue); this.$inScrollAnimation = true; - + clearInterval(this.$timer); _self.session.setScrollTop(steps.shift()); @@ -1077,18 +1077,20 @@ var VirtualRenderer = function(container, theme) { _self.session.setScrollTop(steps.shift()); // trick session to think it's already scrolled to not loose toValue _self.session.$scrollTop = toValue; - } else { - _self.$inScrollAnimation = false; - clearInterval(_self.$timer); - + } else if (toValue != null) { _self.session.$scrollTop = -1; _self.session.setScrollTop(toValue); + toValue = null; + } else { + // do this on separate step to not get spurious scroll event from scrollbar + _self.$timer = clearInterval(_self.$timer); + _self.$inScrollAnimation = false; callback && callback(); } }, 10); } }; - + /** * VirtualRenderer.scrollToY(scrollTop) -> Number * - scrollTop (Number): The position to scroll to From 2502f319f42ec09d154641d1a4fe2ea5d9ac2faa Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 11 May 2012 16:19:30 +0400 Subject: [PATCH 12/40] unclutter gutter and fix sizing --- lib/ace/layer/gutter.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index e700dc76..6b5036ee 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -72,7 +72,7 @@ var Gutter = function(parentEl) { }; this.removeGutterDecoration = function(row, className){ - this.$decorations[row] = this.$decorations[row].replace(" " + className, ""); + this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, ""); }; this.setBreakpoints = function(rows) { @@ -132,7 +132,7 @@ var Gutter = function(parentEl) { this.$breakpoints[i] ? " ace_breakpoint " : " ", annotation.className, "' title='", annotation.text.join("\n"), - "' style='height:", config.lineHeight, "px;'>", (i+1)); + "' style='height:", this.session.getRowLength(i) * config.lineHeight, "px;'>", (i+1)); if (foldWidgets) { var c = foldWidgets[i]; @@ -147,15 +147,18 @@ var Gutter = function(parentEl) { ); } - var wrappedRowLength = this.session.getRowLength(i) - 1; - while (wrappedRowLength--) { - html.push("
\xA6"); - } - html.push("
"); i++; } + + if (this.session.$useWrapMode) + html.push( + "
", + this.session.getLength() - 1, + "
" + ); + this.element = dom.setInnerHtml(this.element, html.join("")); this.element.style.height = config.minHeight + "px"; From acc3faf42ce69d004656d3b32b1be79b95954c87 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 13 May 2012 15:08:48 +0400 Subject: [PATCH 13/40] highlight full gutter line for wrapped lines too --- lib/ace/css/editor.css | 6 ---- lib/ace/virtual_renderer.js | 58 ++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index aad4d2bf..f8dd6bf4 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -27,12 +27,6 @@ z-index: 4; } -.ace_gutter_active_line { - position: absolute; - left: 0; - right: 0; -} - .ace_scroller.horscroll { box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset; } diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index d264c7cf..e80ca2c6 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -67,7 +67,7 @@ dom.importCssString(editorCss, "ace_editor"); /** * new VirtualRenderer(container, theme) - * - container (DOMElement): The root element of the editor + * - container (DOMElement): The root element of the editor * - theme (String): The starting theme * * Constructs a new `VirtualRenderer` within the `container` specified, applying the given `theme`. @@ -82,7 +82,7 @@ var VirtualRenderer = function(container, theme) { // TODO: this breaks rendering in Cloud9 with multiple ace instances // // Imports CSS once per DOM document ('ace_editor' serves as an identifier). // dom.importCssString(editorCss, "ace_editor", container.ownerDocument); - + // in IE <= 9 the native cursor always shines through this.$keepTextAreaAtCursor = !useragent.isIE; @@ -102,7 +102,6 @@ var VirtualRenderer = function(container, theme) { this.content.className = "ace_content"; this.scroller.appendChild(this.content); - this.setHighlightGutterLine(true); this.$gutterLayer = new GutterLayer(this.$gutter); this.$gutterLayer.on("changeGutterWidth", this.onResize.bind(this, true)); this.setFadeFoldWidgets(true); @@ -449,31 +448,38 @@ var VirtualRenderer = function(container, theme) { dom.removeCssClass(this.$gutter, "ace_fade-fold-widgets"); }; - this.$highlightGutterLine = false; + this.$highlightGutterLine = true; this.setHighlightGutterLine = function(shouldHighlight) { if (this.$highlightGutterLine == shouldHighlight) return; this.$highlightGutterLine = shouldHighlight; - - - if (!this.$gutterLineHighlight) { - this.$gutterLineHighlight = dom.createElement("div"); - this.$gutterLineHighlight.className = "ace_gutter_active_line"; - this.$gutter.appendChild(this.$gutterLineHighlight); - return; - } - this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; - this.$updateGutterLineHighlight(); + this.$loop.schedule(this.CHANGE_GUTTER); }; this.getHighlightGutterLine = function() { return this.$highlightGutterLine; }; - this.$updateGutterLineHighlight = function() { - this.$gutterLineHighlight.style.top = this.$cursorLayer.$pixelPos.top - this.layerConfig.offset + "px"; - this.$gutterLineHighlight.style.height = this.layerConfig.lineHeight + "px"; + this.$updateGutterLineHighlight = function(gutterReady) { + var i = this.session.selection.lead.row; + if (i == this.$gutterLineHighlight) + return; + + if (!gutterReady) { + var ch = this.$gutterLayer.element.children + var oldEl = ch[this.$gutterLineHighlight - this.layerConfig.firstRow]; + if (oldEl) + dom.removeCssClass(oldEl, "ace_gutter_active_line"); + + var newEl = ch[i - this.layerConfig.firstRow]; + if (newEl) + dom.addCssClass(newEl, "ace_gutter_active_line"); + } + + this.$gutterLayer.removeGutterDecoration(this.$gutterLineHighlight, "ace_gutter_active_line"); + this.$gutterLayer.addGutterDecoration(i, "ace_gutter_active_line"); + this.$gutterLineHighlight = i; }; this.$updatePrintMargin = function() { @@ -667,13 +673,15 @@ var VirtualRenderer = function(container, theme) { // update scrollbar first to not lose scroll position when gutter calls resize this.$updateScrollBar(); this.$textLayer.update(this.layerConfig); - if (this.showGutter) + if (this.showGutter) { + if (this.$highlightGutterLine) + this.$updateGutterLineHighlight(true); this.$gutterLayer.update(this.layerConfig); + } this.$markerBack.update(this.layerConfig); this.$markerFront.update(this.layerConfig); this.$cursorLayer.update(this.layerConfig); this.$moveTextAreaToCursor(); - this.$highlightGutterLine && this.$updateGutterLineHighlight(); return; } @@ -685,13 +693,15 @@ var VirtualRenderer = function(container, theme) { else this.$textLayer.scrollLines(this.layerConfig); - if (this.showGutter) + if (this.showGutter) { + if (this.$highlightGutterLine) + this.$updateGutterLineHighlight(true); this.$gutterLayer.update(this.layerConfig); + } this.$markerBack.update(this.layerConfig); this.$markerFront.update(this.layerConfig); this.$cursorLayer.update(this.layerConfig); this.$moveTextAreaToCursor(); - this.$highlightGutterLine && this.$updateGutterLineHighlight(); return; } @@ -714,7 +724,7 @@ var VirtualRenderer = function(container, theme) { if (changes & this.CHANGE_CURSOR) { this.$cursorLayer.update(this.layerConfig); this.$moveTextAreaToCursor(); - this.$highlightGutterLine && this.$updateGutterLineHighlight(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(false); } if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) { @@ -1041,13 +1051,13 @@ var VirtualRenderer = function(container, theme) { return steps; }; - /** + /** * VirtualRenderer.scrollToLine(line, center, animate, callback) -> Void * - line (Number): A line number * - center (Boolean): If `true`, centers the editor the to indicated line * - animate (Boolean): If `true` animates scrolling * - callback (Function): Function to be called after the animation has finished - * + * * Gracefully scrolls the editor to the row indicated. **/ this.scrollToLine = function(line, center, animate, callback) { From 806114aa2e84ad3db2e811734f3799f6087ea42b Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 25 May 2012 11:12:44 +0400 Subject: [PATCH 14/40] tweak fadeFoldWidgets animation --- lib/ace/css/editor.css | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index f8dd6bf4..c1cd0f0c 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -192,13 +192,13 @@ box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; - + display: inline-block; height: 11px; margin-top: -2px; vertical-align: middle; - background-image: + background-image: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82"), url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82"); background-repeat: no-repeat, repeat-x; @@ -209,7 +209,7 @@ -moz-border-radius: 2px; -webkit-border-radius: 2px; border-radius: 2px; - + cursor: pointer; pointer-events: auto; } @@ -218,7 +218,7 @@ } .ace_fold:hover{ - background-image: + background-image: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82"), url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82"); background-repeat: no-repeat, repeat-x; @@ -243,7 +243,7 @@ height: 14px; width: 11px; vertical-align: text-bottom; - + background-image: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82"); background-repeat: no-repeat; background-position: center 5px; @@ -288,23 +288,19 @@ } .ace_fade-fold-widgets .ace_fold-widget { - -moz-transition: 0.5s opacity; - -webkit-transition: 0.5s opacity; - -o-transition: 0.5s opacity; - -ms-transition: 0.5s opacity; - transition: 0.5s opacity; + -moz-transition: opacity 0.4s ease 0.05s; + -webkit-transition: opacity 0.4s ease 0.05s; + -o-transition: opacity 0.4s ease 0.05s; + -ms-transition: opacity 0.4s ease 0.05s; + transition: opacity 0.4s ease 0.05s; opacity: 0; } + .ace_fade-fold-widgets:hover .ace_fold-widget { - -moz-transition-duration: 0.05s; - -webkit-transition-duration: 0.05s; - -o-transition-duration: 0.05s; - -ms-transition-duration: 0.05s; - transition-duration: 0.05s; - -moz-transition-delay: 0.2s; - -webkit-transition-delay: 0.2s; - -o-transition-delay: 0.2s; - -ms-transition-delay: 0.2s; - transition-delay: 0.2s; + -moz-transition: opacity 0.05s ease 0.05s; + -webkit-transition: opacity 0.05s ease 0.05s; + -o-transition: opacity 0.05s ease 0.05s; + -ms-transition: opacity 0.05s ease 0.05s; + transition: opacity 0.05s ease 0.05s; opacity:1; } From 6e1215a45ee3246752c9d884f72db08f3543f93f Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 25 May 2012 11:28:20 +0400 Subject: [PATCH 15/40] small cleanups --- lib/ace/commands/command_manager.js | 15 +- lib/ace/commands/multi_select_commands.js | 12 +- lib/ace/config.js | 4 +- lib/ace/editor.js | 33 ++++- lib/ace/keyboard/hash_handler.js | 7 +- lib/ace/keyboard/keybinding.js | 3 +- lib/ace/keyboard/vim.js | 4 +- lib/ace/keyboard/vim/commands.js | 27 ++-- lib/ace/mouse/default_gutter_handler.js | 1 + lib/ace/mouse/default_handlers.js | 18 +-- lib/ace/multi_select.js | 11 +- lib/ace/selection.js | 161 +++++++++++----------- lib/ace/test/all_browser.js | 12 +- 13 files changed, 172 insertions(+), 136 deletions(-) diff --git a/lib/ace/commands/command_manager.js b/lib/ace/commands/command_manager.js index b919dbc1..5eab67be 100644 --- a/lib/ace/commands/command_manager.js +++ b/lib/ace/commands/command_manager.js @@ -51,16 +51,11 @@ oop.inherits(CommandManager, HashHandler); if (editor && editor.$readOnly && !command.readOnly) return false; - try { - var retvalue = this._emit("exec", { - editor: editor, - command: command, - args: args - }); - } catch (e) { - window.console && window.console.log(e); - return true; - } + var retvalue = this._emit("exec", { + editor: editor, + command: command, + args: args + }); return retvalue === false ? false : true; }; diff --git a/lib/ace/commands/multi_select_commands.js b/lib/ace/commands/multi_select_commands.js index a3c1a16d..ed396fb3 100644 --- a/lib/ace/commands/multi_select_commands.js +++ b/lib/ace/commands/multi_select_commands.js @@ -79,12 +79,15 @@ exports.defaultCommands = [{ 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.multiSelectCommands = [{ name: "singleSelection", bindKey: "esc", exec: function(editor) { editor.exitMultiSelectMode(); }, @@ -92,10 +95,7 @@ exports.defaultCommands = [{ isAvailable: function(editor) {return editor.inMultiSelectMode} }]; -// commands active in multiselect mode -exports.multiEditCommands = {"singleSelection": "esc"}; - var HashHandler = require("../keyboard/hash_handler").HashHandler; -exports.keyboardHandler = new HashHandler(exports.multiEditCommands); +exports.keyboardHandler = new HashHandler(exports.multiSelectCommands); }); diff --git a/lib/ace/config.js b/lib/ace/config.js index 17bbab5d..73a83d51 100644 --- a/lib/ace/config.js +++ b/lib/ace/config.js @@ -55,14 +55,14 @@ var options = { exports.get = function(key) { if (!options.hasOwnProperty(key)) - throw new Error("Unknown confik key: " + key); + throw new Error("Unknown config key: " + key); return options[key]; }; exports.set = function(key, value) { if (!options.hasOwnProperty(key)) - throw new Error("Unknown confik key: " + key); + throw new Error("Unknown config key: " + key); options[key] = value; }; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 834e603a..7534081e 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -235,6 +235,35 @@ var Editor = function(renderer, session) { return this.session; }; + /** related to: Document.setValue + * Editor.setValue(val [,dontSelect]) -> String + * - val (String): The new value to set for the document + * - cursorPos (number): 0: selectAll, -1 document start, 1 end + * + * Sets the current document to `val`. + **/ + this.setValue = function(val, cursorPos) { + this.session.doc.setValue(val); + + if (!cursorPos) + this.selectAll(); + else if (cursorPos == 1) + this.navigateFileEnd(); + else if (cursorPos == -1) + this.navigateFileStart(); + + return val; + }; + + /** related to: EditSession.getValue + * Editor.getValue() -> String + * + * Returns the current session's content. + **/ + this.getValue = function() { + return this.session.getValue(); + }; + /** * Editor.getSelection() -> String * @@ -249,8 +278,8 @@ var Editor = function(renderer, session) { * * {:VirtualRenderer.onResize} **/ - this.resize = function() { - this.renderer.onResize(); + this.resize = function(force) { + this.renderer.onResize(force); }; /** diff --git a/lib/ace/keyboard/hash_handler.js b/lib/ace/keyboard/hash_handler.js index d3d4f524..3fad3339 100644 --- a/lib/ace/keyboard/hash_handler.js +++ b/lib/ace/keyboard/hash_handler.js @@ -57,9 +57,8 @@ function HashHandler(config, platform) { this.commands[command.name] = command; - if (command.bindKey) { + if (command.bindKey) this._buildKeyHash(command); - } }; this.removeCommand = function(command) { @@ -81,6 +80,10 @@ function HashHandler(config, platform) { this.bindKey = function(key, command) { if(!key) return; + if (typeof command == "function") { + this.addCommand({exec: command, bindKey: key, name: key}); + return; + } var ckb = this.commmandKeyBinding; key.split("|").forEach(function(keyPart) { diff --git a/lib/ace/keyboard/keybinding.js b/lib/ace/keyboard/keybinding.js index 2c336438..80bf0de1 100644 --- a/lib/ace/keyboard/keybinding.js +++ b/lib/ace/keyboard/keybinding.js @@ -119,7 +119,8 @@ var KeyBinding = function(editor) { else success = toExecute.passEvent != true; - if (success && e) + // do not stop input events to not break repeating + if (success && e && hashId != -1) event.stopEvent(e); return success; diff --git a/lib/ace/keyboard/vim.js b/lib/ace/keyboard/vim.js index 26016d34..c5dc54e8 100644 --- a/lib/ace/keyboard/vim.js +++ b/lib/ace/keyboard/vim.js @@ -108,7 +108,9 @@ exports.handler = { editor.removeListener("click", exports.onCursorMove); util.noMode(editor); util.currentMode = "normal"; - } + }, + + actions: cmds.actions }; diff --git a/lib/ace/keyboard/vim/commands.js b/lib/ace/keyboard/vim/commands.js index 9f802a42..85ab7f68 100644 --- a/lib/ace/keyboard/vim/commands.js +++ b/lib/ace/keyboard/vim/commands.js @@ -52,18 +52,6 @@ var MOTION = 3; var ACTION = 4; var HMARGIN = 8; // Minimum amount of line separation between margins; -exports.searchStore = { - current: "", - options: { - needle: "", - backwards: false, - wrap: true, - caseSensitive: false, - wholeWord: false, - regExp: false - } -}; - var repeat = function repeat(fn, count, args) { while (0 < count--) fn.apply(this, args); @@ -88,7 +76,7 @@ var ensureScrollMargin = function(editor) { } }; -var actions = { +var actions = exports.actions = { "z": { param: true, fn: function(editor, range, count, param) { @@ -288,16 +276,17 @@ var actions = { }, ":": { fn: function(editor, range, count, param) { - editor.blur(); - txtConsoleInput.focus(); - txtConsoleInput.setValue(":"); + // not implemented } }, "/": { fn: function(editor, range, count, param) { - editor.blur(); - txtConsoleInput.focus(); - txtConsoleInput.setValue("/"); + // not implemented + } + }, + "?": { + fn: function(editor, range, count, param) { + // not implemented } }, ".": { 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 8c804f2b..5b2a8413 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)); @@ -69,14 +65,16 @@ 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; @@ -99,7 +97,10 @@ function DefaultHandlers(mouseHandler) { // selection if (inSelection && !editor.isFocused()) { editor.focus(); - return; + if (this.$focusWaitTimout && !this.$clickSelection) { + // todo start select after focusWaitTimout passes + return; + } } if (!inSelection || this.$clickSelection || ev.getShiftKey()) { @@ -116,7 +117,8 @@ function DefaultHandlers(mouseHandler) { } } - this.captureMouse(ev) + this.captureMouse(ev); + return ev.preventDefault(); }; this.startSelect = function(pos) { 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/selection.js b/lib/ace/selection.js index 5def4061..062c847b 100644 --- a/lib/ace/selection.js +++ b/lib/ace/selection.js @@ -55,7 +55,7 @@ var Range = require("./range").Range; /** * new Selection(session) * - session (EditSession): The session to use - * + * * Creates a new `Selection` object. * **/ @@ -88,7 +88,7 @@ var Selection = function(session) { /** * Selection.isEmpty() -> Boolean - * + * * Returns `true` if the selection is empty. **/ this.isEmpty = function() { @@ -100,7 +100,7 @@ var Selection = function(session) { /** * Selection.isMultiLine() -> Boolean - * + * * Returns `true` if the selection is a multi-line. **/ this.isMultiLine = function() { @@ -113,7 +113,7 @@ var Selection = function(session) { /** * Selection.getCursor() -> Number - * + * * Gets the current position of the cursor. **/ this.getCursor = function() { @@ -121,7 +121,7 @@ var Selection = function(session) { }; /** - * Selection.setSelectionAnchor(row, column) + * Selection.setSelectionAnchor(row, column) * - row (Number): The new row * - column (Number): The new column * @@ -138,7 +138,7 @@ var Selection = function(session) { /** related to: Anchor.getPosition * Selection.getSelectionAnchor() -> Object - * + * * Returns an object containing the `row` and `column` of the calling selection anchor. * **/ @@ -149,9 +149,9 @@ var Selection = function(session) { return this.anchor.getPosition(); }; - /** + /** * Selection.getSelectionLead() -> Object - * + * * Returns an object containing the `row` and `column` of the calling selection lead. **/ this.getSelectionLead = function() { @@ -159,9 +159,9 @@ var Selection = function(session) { }; /** - * Selection.shiftSelection(columns) + * Selection.shiftSelection(columns) * - columns (Number): The number of columns to shift by - * + * * Shifts the selection up (or down, if [[Selection.isBackwards `isBackwards()`]] is true) the given number of columns. * **/ @@ -188,7 +188,7 @@ var Selection = function(session) { /** * Selection.isBackwards() -> Boolean - * + * * Returns `true` if the selection is going backwards in the document. **/ this.isBackwards = function() { @@ -199,7 +199,7 @@ var Selection = function(session) { /** * Selection.getRange() -> Range - * + * * [Returns the [[Range `Range`]] for the selected text.]{: #Selection.getRange} **/ this.getRange = function() { @@ -218,8 +218,8 @@ var Selection = function(session) { }; /** - * Selection.clearSelection() - * + * Selection.clearSelection() + * * [Empties the selection (by de-selecting it). This function also emits the `'changeSelection'` event.]{: #Selection.clearSelection} **/ this.clearSelection = function() { @@ -230,24 +230,25 @@ var Selection = function(session) { }; /** - * Selection.selectAll() - * + * Selection.selectAll() + * * Selects all the text in the document. **/ this.selectAll = function() { var lastRow = this.doc.getLength() - 1; - this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length); - this.moveCursorTo(0, 0); + this.setSelectionAnchor(0, 0); + this.moveCursorTo(lastRow, this.doc.getLine(lastRow).length); }; /** - * Selection.setSelectionRange(range, reverse) + * Selection.setSelectionRange(range, reverse) * - range (Range): The range of text to select * - reverse (Boolean): Indicates if the range should go backwards (`true`) or not * * Sets the selection to the provided range. * **/ + this.setRange = this.setSelectionRange = function(range, reverse) { if (reverse) { this.setSelectionAnchor(range.end.row, range.end.column); @@ -268,7 +269,7 @@ var Selection = function(session) { }; /** - * Selection.selectTo(row, column) + * Selection.selectTo(row, column) * - row (Number): The row to select to * - column (Number): The column to select to * @@ -282,9 +283,9 @@ var Selection = function(session) { }; /** - * Selection.selectToPosition(pos) + * Selection.selectToPosition(pos) * - pos (Object): An object containing the row and column - * + * * Moves the selection cursor to the row and column indicated by `pos`. * **/ @@ -295,8 +296,8 @@ var Selection = function(session) { }; /** - * Selection.selectUp() - * + * Selection.selectUp() + * * Moves the selection up one row. **/ this.selectUp = function() { @@ -304,8 +305,8 @@ var Selection = function(session) { }; /** - * Selection.selectDown() - * + * Selection.selectDown() + * * Moves the selection down one row. **/ this.selectDown = function() { @@ -313,8 +314,8 @@ var Selection = function(session) { }; /** - * Selection.selectRight() - * + * Selection.selectRight() + * * Moves the selection right one column. **/ this.selectRight = function() { @@ -322,8 +323,8 @@ var Selection = function(session) { }; /** - * Selection.selectLeft() - * + * Selection.selectLeft() + * * Moves the selection left one column. **/ this.selectLeft = function() { @@ -331,8 +332,8 @@ var Selection = function(session) { }; /** - * Selection.selectLineStart() - * + * Selection.selectLineStart() + * * Moves the selection to the beginning of the current line. **/ this.selectLineStart = function() { @@ -340,8 +341,8 @@ var Selection = function(session) { }; /** - * Selection.selectLineEnd() - * + * Selection.selectLineEnd() + * * Moves the selection to the end of the current line. **/ this.selectLineEnd = function() { @@ -349,8 +350,8 @@ var Selection = function(session) { }; /** - * Selection.selectFileEnd() - * + * Selection.selectFileEnd() + * * Moves the selection to the end of the file. **/ this.selectFileEnd = function() { @@ -358,8 +359,8 @@ var Selection = function(session) { }; /** - * Selection.selectFileStart() - * + * Selection.selectFileStart() + * * Moves the selection to the start of the file. **/ this.selectFileStart = function() { @@ -367,8 +368,8 @@ var Selection = function(session) { }; /** - * Selection.selectWordRight() - * + * Selection.selectWordRight() + * * Moves the selection to the first word on the right. **/ this.selectWordRight = function() { @@ -376,8 +377,8 @@ var Selection = function(session) { }; /** - * Selection.selectWordLeft() - * + * Selection.selectWordLeft() + * * Moves the selection to the first word on the left. **/ this.selectWordLeft = function() { @@ -385,8 +386,8 @@ var Selection = function(session) { }; /** related to: EditSession.getWordRange - * Selection.selectWord() - * + * Selection.selectWord() + * * Moves the selection to highlight the entire word. **/ this.getWordRange = function(row, column) { @@ -403,8 +404,8 @@ var Selection = function(session) { }; /** related to: EditSession.getAWordRange - * Selection.selectAWord() - * + * Selection.selectAWord() + * * Selects a word, including its right whitespace. **/ this.selectAWord = function() { @@ -430,9 +431,9 @@ var Selection = function(session) { return new Range(rowStart, 0, rowEnd + 1, 0); }; - /** - * Selection.selectLine() - * + /** + * Selection.selectLine() + * * Selects the entire line. **/ this.selectLine = function() { @@ -440,8 +441,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorUp() - * + * Selection.moveCursorUp() + * * Moves the cursor up one row. **/ this.moveCursorUp = function() { @@ -449,8 +450,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorDown() - * + * Selection.moveCursorDown() + * * Moves the cursor down one row. **/ this.moveCursorDown = function() { @@ -458,8 +459,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorLeft() - * + * Selection.moveCursorLeft() + * * Moves the cursor left one column. **/ this.moveCursorLeft = function() { @@ -484,8 +485,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorRight() - * + * Selection.moveCursorRight() + * * Moves the cursor right one column. **/ this.moveCursorRight = function() { @@ -510,8 +511,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorLineStart() - * + * Selection.moveCursorLineStart() + * * Moves the cursor to the start of the line. **/ this.moveCursorLineStart = function() { @@ -543,8 +544,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorLineEnd() - * + * Selection.moveCursorLineEnd() + * * Moves the cursor to the end of the line. **/ this.moveCursorLineEnd = function() { @@ -558,8 +559,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorFileEnd() - * + * Selection.moveCursorFileEnd() + * * Moves the cursor to the end of the file. **/ this.moveCursorFileEnd = function() { @@ -569,8 +570,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorFileStart() - * + * Selection.moveCursorFileStart() + * * Moves the cursor to the start of the file. **/ this.moveCursorFileStart = function() { @@ -578,8 +579,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorLongWordRight() - * + * Selection.moveCursorLongWordRight() + * * Moves the cursor to the word on the right. **/ this.moveCursorLongWordRight = function() { @@ -598,14 +599,14 @@ var Selection = function(session) { this.moveCursorTo(fold.end.row, fold.end.column); return; } - + // first skip space if (match = this.session.nonTokenRe.exec(rightOfCursor)) { column += this.session.nonTokenRe.lastIndex; this.session.nonTokenRe.lastIndex = 0; rightOfCursor = line.substring(column); } - + // if at line end proceed with next line if (column >= line.length) { this.moveCursorTo(row, line.length); @@ -614,7 +615,7 @@ var Selection = function(session) { this.moveCursorWordRight(); return; } - + // advance to the end of the next token if (match = this.session.tokenRe.exec(rightOfCursor)) { column += this.session.tokenRe.lastIndex; @@ -625,8 +626,8 @@ var Selection = function(session) { }; /** - * Selection.moveCursorLongWordLeft() - * + * Selection.moveCursorLongWordLeft() + * * Moves the cursor to the word on the left. **/ this.moveCursorLongWordLeft = function() { @@ -644,19 +645,19 @@ var Selection = function(session) { if (str == null) { str = this.doc.getLine(row).substring(0, column) } - + var leftOfCursor = lang.stringReverse(str); var match; this.session.nonTokenRe.lastIndex = 0; this.session.tokenRe.lastIndex = 0; - + // skip whitespace if (match = this.session.nonTokenRe.exec(leftOfCursor)) { column -= this.session.nonTokenRe.lastIndex; leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex); this.session.nonTokenRe.lastIndex = 0; } - + // if at begin of the line proceed in line above if (column <= 0) { this.moveCursorTo(row, 0); @@ -762,7 +763,7 @@ var Selection = function(session) { }; /** related to: EditSession.documentToScreenPosition - * Selection.moveCursorBy(rows, chars) + * Selection.moveCursorBy(rows, chars) * - rows (Number): The number of rows to move by * - chars (Number): The number of characters to move by * @@ -788,9 +789,9 @@ var Selection = function(session) { }; /** - * Selection.moveCursorToPosition(position) + * Selection.moveCursorToPosition(position) * - position (Object): The position to move to - * + * * Moves the selection to the position indicated by its `row` and `column`. **/ this.moveCursorToPosition = function(position) { @@ -798,7 +799,7 @@ var Selection = function(session) { }; /** - * Selection.moveCursorTo(row, column, keepDesiredColumn) + * Selection.moveCursorTo(row, column, keepDesiredColumn) * - row (Number): The row to move to * - column (Number): The column to move to * - keepDesiredColumn (Boolean): [If `true`, the cursor move does not respect the previous column]{: #preventUpdateBool} @@ -822,7 +823,7 @@ var Selection = function(session) { }; /** - * Selection.moveCursorToScreen(row, column, keepDesiredColumn) + * Selection.moveCursorToScreen(row, column, keepDesiredColumn) * - row (Number): The row to move to * - column (Number): The column to move to * - keepDesiredColumn (Boolean): {:preventUpdateBool} diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index d6c349f7..b9987b69 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -65,7 +65,11 @@ if (location.search) testNames = location.search.substr(1).split(",") require(testNames, function() { - var tests = testNames.map(require); + var tests = testNames.map(function(x) { + var module = require(x); + module.href = x; + return module; + }); async.list(tests) .expand(function(test) { @@ -73,6 +77,12 @@ require(testNames, function() { }, AsyncTest.TestGenerator) .run() .each(function(test, next) { + if (test.index == 1 && test.context.href) { + var href = test.context.href; + var node = document.createElement("div"); + node.innerHTML = "" + href.replace(/^ace\//, "") + ""; + log.appendChild(node); + } var node = document.createElement("div"); node.className = test.passed ? "passed" : "failed"; From b3ffdeda6edba78b6dae2bb5fbaa0ec437cbdfd6 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 10 May 2012 13:40:02 +0400 Subject: [PATCH 16/40] fix c# and go highlight rules --- lib/ace/mode/csharp_highlight_rules.js | 4 ++-- lib/ace/mode/golang_highlight_rules.js | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/ace/mode/csharp_highlight_rules.js b/lib/ace/mode/csharp_highlight_rules.js index bbb53697..7713e40b 100644 --- a/lib/ace/mode/csharp_highlight_rules.js +++ b/lib/ace/mode/csharp_highlight_rules.js @@ -26,7 +26,7 @@ var CSharpHighlightRules = function() { token : "comment", regex : "\\/\\/.*$" }, - new DocCommentHighlightRules().getStartRule("doc-start"), + DocCommentHighlightRules.getStartRule("doc-start"), { token : "comment", // multi line comment regex : "\\/\\*", @@ -95,7 +95,7 @@ var CSharpHighlightRules = function() { }; this.embedRules(DocCommentHighlightRules, "doc-", - [ new DocCommentHighlightRules().getEndRule("start") ]); + [ DocCommentHighlightRules.getEndRule("start") ]); }; oop.inherits(CSharpHighlightRules, TextHighlightRules); diff --git a/lib/ace/mode/golang_highlight_rules.js b/lib/ace/mode/golang_highlight_rules.js index e0d09ec6..b899057b 100644 --- a/lib/ace/mode/golang_highlight_rules.js +++ b/lib/ace/mode/golang_highlight_rules.js @@ -119,6 +119,9 @@ define(function(require, exports, module) { } ] }; + + this.embedRules(DocCommentHighlightRules, "doc-", + [ DocCommentHighlightRules.getEndRule("start") ]); } oop.inherits(GolangHighlightRules, TextHighlightRules); From 31729a963a6f2e909d6742ca2f670c3fac685dab Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 19 May 2012 20:38:09 +0400 Subject: [PATCH 17/40] do not store copy of breakpoints array in gutter --- lib/ace/editor.js | 2 +- lib/ace/layer/gutter.js | 7 ++----- lib/ace/test/mockrenderer.js | 2 +- lib/ace/virtual_renderer.js | 8 +++----- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 7534081e..eddd7cf1 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -570,7 +570,7 @@ var Editor = function(renderer, session) { * Emitted when a breakpoint changes. **/ this.onChangeBreakpoint = function() { - this.renderer.setBreakpoints(this.session.getBreakpoints()); + this.renderer.updateBreakpoints(); }; /** diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 6b5036ee..be72a172 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -75,10 +75,6 @@ var Gutter = function(parentEl) { this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, ""); }; - this.setBreakpoints = function(rows) { - this.$breakpoints = rows.concat(); - }; - this.setAnnotations = function(annotations) { // iterate over sparse array this.$annotations = []; @@ -116,6 +112,7 @@ var Gutter = function(parentEl) { var fold = this.session.getNextFoldLine(i); var foldStart = fold ? fold.start.row : Infinity; var foldWidgets = this.$showFoldWidgets && this.session.foldWidgets; + var breakpoints = this.session.$breakpoints; while (true) { if(i > foldStart) { @@ -129,7 +126,7 @@ var Gutter = function(parentEl) { var annotation = this.$annotations[i] || emptyAnno; html.push("
", (i+1)); diff --git a/lib/ace/test/mockrenderer.js b/lib/ace/test/mockrenderer.js index 381a7918..4e5c515d 100644 --- a/lib/ace/test/mockrenderer.js +++ b/lib/ace/test/mockrenderer.js @@ -163,7 +163,7 @@ MockRenderer.prototype.updateBackMarkers = function() { MockRenderer.prototype.updateFrontMarkers = function() { }; -MockRenderer.prototype.setBreakpoints = function() { +MockRenderer.prototype.updateBreakpoints = function() { }; MockRenderer.prototype.onResize = function() { diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index e80ca2c6..88719079 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -889,13 +889,11 @@ var VirtualRenderer = function(container, theme) { }; /** - * VirtualRenderer.setBreakpoints(rows) -> Void - * - rows (Array): An array containg row numbers + * VirtualRenderer.updateBreakpoints() -> Void * - * Sets a breakpoint for every row number indicated on `rows`. + * Redraw breakpoints. **/ - this.setBreakpoints = function(rows) { - this.$gutterLayer.setBreakpoints(rows); + this.updateBreakpoints = function(rows) { this.$loop.schedule(this.CHANGE_GUTTER); }; From 3d774aa2b69b5b3292d935ec156a2175bc373f4c Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 25 May 2012 21:15:38 +0400 Subject: [PATCH 18/40] search rewrite --- lib/ace/editor.js | 83 +++++---- lib/ace/lib/lang.js | 14 ++ lib/ace/search.js | 405 +++++++++++++++++++---------------------- lib/ace/search_test.js | 67 +++++-- 4 files changed, 300 insertions(+), 269 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 834e603a..6576452d 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -1954,65 +1954,84 @@ var Editor = function(renderer, session) { }; /** related to: Search.find - * Editor.find(needle, options) - * - needle (String): The text to search for + * Editor.find(needle, options) + * - needle (String): The text to search for (optional) * - options (Object): An object defining various search properties * - animate (Boolean): If `true` animate scrolling * * Attempts to find `needle` within the document. For more information on `options`, see [[Search `Search`]]. **/ this.find = function(needle, options, animate) { - this.clearSelection(); - options = options || {}; - options.needle = needle; + if (!options) + options = {}; + + if (typeof needle == "string" || needle instanceof RegExp) + options.needle = needle; + else if (typeof needle == "object") + oop.mixin(options, needle); + + var range = this.selection.getRange(); + if (options.needle == null) { + needle = this.session.getTextRange(range) + || this.$search.$options.needle; + if (!needle) { + range = this.session.getWordRange(range.start.row, range.start.column); + needle = this.session.getTextRange(range); + } + this.$search.set({needle: needle}); + } + this.$search.set(options); - this.$find(options.backwards, animate); + if (!options.start) + this.$search.set({start: range}); + + var newRange = this.$search.find(this.session); + if (options.preventScroll) + return newRange; + if (newRange) { + this.revealRange(newRange, animate); + return newRange; + } + // clear selection if nothing is found + if (options.backwards) + range.start = range.end; + else + range.end = range.start; + this.selection.setRange(range); }; /** related to: Editor.find - * Editor.findNext(options) + * Editor.findNext(options) * - options (Object): search options * - animate (Boolean): If `true` animate scrolling - * + * * Performs another search for `needle` in the document. For more information on `options`, see [[Search `Search`]]. **/ this.findNext = function(options, animate) { - options = options || {}; - this.$search.set(options); - this.$find(false, animate); + this.find({skipCurrent: true, backwards: false}, options, animate); }; /** related to: Editor.find - * Editor.findPrevious(options) + * Editor.findPrevious(options) * - options (Object): search options * - animate (Boolean): If `true` animate scrolling - * + * * Performs a search for `needle` backwards. For more information on `options`, see [[Search `Search`]]. **/ this.findPrevious = function(options, animate) { - options = options || {}; - this.$search.set(options); - this.$find(true, animate); + this.find(options, {skipCurrent: true, backwards: true}, animate); }; - this.$find = function(backwards, animate) { - if (!this.selection.isEmpty()) - this.$search.set({needle: this.session.getTextRange(this.getSelectionRange())}); + this.revealRange = function(range, animate) { + this.$blockScrolling += 1; + this.session.unfold(range); + this.selection.setSelectionRange(range); + this.$blockScrolling -= 1; - if (typeof backwards != "undefined") - this.$search.set({backwards: backwards}); - - var range = this.$search.find(this.session); - if (range) { - this.$blockScrolling += 1; - this.session.unfold(range); - this.selection.setSelectionRange(range); - this.$blockScrolling -= 1; - - var scrollTop = this.renderer.scrollTop; - this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5); + var scrollTop = this.renderer.scrollTop; + this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5); + if (animate != false) this.renderer.animateScrolling(scrollTop); - } }; /** related to: UndoManager.undo diff --git a/lib/ace/lib/lang.js b/lib/ace/lib/lang.js index c8b7afa3..3b862bdb 100644 --- a/lib/ace/lib/lang.js +++ b/lib/ace/lib/lang.js @@ -116,6 +116,20 @@ exports.escapeRegExp = function(str) { return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); }; +exports.getMatchOffsets = function(string, regExp) { + var matches = []; + + string.replace(regExp, function(str) { + matches.push({ + offset: arguments[arguments.length-2], + length: str.length + }); + }); + + return matches; +}; + + exports.deferredCall = function(fcn) { var timer = null; diff --git a/lib/ace/search.js b/lib/ace/search.js index dedcadea..38e96ea6 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 ae 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 lastRow) { - if (wrap) { - row = firstRow; - startIndex = firstColumn; - inWrap = true; - } else { - return; - } - } - - if (row == start.row) - stop = true; - - line = getLine(row); - } + for (row = firstRow, lastRow = start.row; row <= lastRow; row++) + if (callback(session.getLine(row), row)) + return; } } else { var forEach = function(callback) { var row = start.row; var line = session.getLine(row).substring(0, start.column); - var startIndex = 0; - var stop = false; - var inWrap = false; + if (callback(line, row)) + return; - while (!callback(line, startIndex, row)) { - if (stop) + for (row--; row >= firstRow; row--) + if (callback(session.getLine(row), row)) return; - row--; - startIndex = 0; + if (options.wrap == false) + return; - if (row < firstRow) { - if (wrap) { - row = lastRow; - inWrap = true; - } else { - return; - } - } - - if (row == start.row) - stop = true; - - line = session.getLine(row); - if (searchSelection) { - if (row == firstRow) - startIndex = firstColumn; - else if (row == lastRow) - line = line.substring(0, range.end.column); - } - - if (inWrap && row == start.row) - startIndex = start.column; - } + for (row = lastRow, firstRow = start.row; row >= firstRow; row--) + if (callback(session.getLine(row), row)) + return; } } diff --git a/lib/ace/search_test.js b/lib/ace/search_test.js index e1f02c46..7a28d89c 100644 --- a/lib/ace/search_test.js +++ b/lib/ace/search_test.js @@ -52,7 +52,6 @@ module.exports = { var search = new Search(); search.set({ needle: "juhu", - scope: Search.ALL }); }, @@ -90,7 +89,7 @@ module.exports = { assert.position(range.end, 1, 12); }, - "test: wrap search is off by default" : function() { + "test: wrap search is on by default" : function() { var session = new EditSession(["abc", "juhu kinners 123", "456"]); session.getSelection().moveCursorTo(2, 1); @@ -98,7 +97,7 @@ module.exports = { needle: "kinners" }); - assert.equal(search.find(session), null); + assert.notEqual(search.find(session), null); }, "test: wrap search should wrap at file end" : function() { @@ -115,6 +114,20 @@ module.exports = { assert.position(range.end, 1, 12); }, + "test: wrap search should find needle even if it starts inside it" : function() { + var session = new EditSession(["abc", "juhu kinners 123", "456"]); + session.getSelection().moveCursorTo(6, 1); + + var search = new Search().set({ + needle: "kinners", + wrap: true + }); + + var range = search.find(session); + assert.position(range.start, 1, 5); + assert.position(range.end, 1, 12); + }, + "test: wrap search with no match should return 'null'": function() { var session = new EditSession(["abc", "juhu kinners 123", "456"]); session.getSelection().moveCursorTo(2, 1); @@ -183,13 +196,19 @@ module.exports = { var search = new Search().set({ needle: "juhu", wrap: true, - scope: Search.SELECTION + range: session.getSelection().getRange() }); var range = search.find(session); assert.position(range.start, 1, 0); assert.position(range.end, 1, 4); + search = new Search().set({ + needle: "juhu", + wrap: true, + range: session.getSelection().getRange() + }); + session.getSelection().setSelectionAnchor(0, 2); session.getSelection().selectTo(3, 2); @@ -201,24 +220,32 @@ module.exports = { "test: find backwards in selection": function() { var session = new EditSession(["juhu", "juhu", "juhu", "juhu"]); + session.getSelection().setSelectionAnchor(0, 2); + session.getSelection().selectTo(3, 2); + var search = new Search().set({ needle: "juhu", wrap: true, backwards: true, - scope: Search.SELECTION + range: session.getSelection().getRange() }); - session.getSelection().setSelectionAnchor(0, 2); - session.getSelection().selectTo(3, 2); - var range = search.find(session); assert.position(range.start, 2, 0); assert.position(range.end, 2, 4); + search = new Search().set({ + needle: "juhu", + wrap: true, + range: session.getSelection().getRange() + }); + session.getSelection().setSelectionAnchor(0, 2); session.getSelection().selectTo(1, 2); - assert.equal(search.find(session), null); + var range = search.find(session); + assert.position(range.start, 1, 0); + assert.position(range.end, 1, 4); }, "test: edge case - match directly before the cursor" : function() { @@ -295,15 +322,15 @@ module.exports = { "test: find all matches in selection" : function() { var session = new EditSession(["juhu", "juhu", "juhu", "juhu"]); + session.getSelection().setSelectionAnchor(0, 2); + session.getSelection().selectTo(3, 2); + var search = new Search().set({ needle: "uh", wrap: true, - scope: Search.SELECTION + range: session.getSelection().getRange() }); - session.getSelection().setSelectionAnchor(0, 2); - session.getSelection().selectTo(3, 2); - var ranges = search.findAll(session); assert.equal(ranges.length, 2); @@ -322,6 +349,11 @@ module.exports = { assert.equal(search.replace("", "kinners"), null); assert.equal(search.replace(" juhu", "kinners"), null); + // case sensitivity + assert.equal(search.replace("Juhu", "kinners"), "kinners"); + search.set({caseSensitive: true}); + assert.equal(search.replace("Juhu", "kinners"), null); + // regexp replacement }, @@ -356,7 +388,6 @@ module.exports = { needle: "[ ]+$", regExp: true, wrap: true, - scope: Search.ALL }); session.getSelection().moveCursorTo(1, 2); @@ -404,12 +435,12 @@ module.exports = { var ranges = search.findAll(session); assert.equal(ranges.length, 3); - assert.position(ranges[0].start, 0, 23); - assert.position(ranges[0].end, 0, 26); + assert.position(ranges[2].start, 0, 23); + assert.position(ranges[2].end, 0, 26); assert.position(ranges[1].start, 0, 8); assert.position(ranges[1].end, 0, 11); - assert.position(ranges[2].start, 0, 0); - assert.position(ranges[2].end, 0, 3); + assert.position(ranges[0].start, 0, 0); + assert.position(ranges[0].end, 0, 3); }, }; From fead610584d0f91eccbbb9079fe1a67addaef3ad Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 25 May 2012 21:23:28 +0400 Subject: [PATCH 19/40] fix multiple clicks and reduce double click timeout --- lib/ace/lib/event.js | 41 +++++++++++++++++++++------------- lib/ace/mouse/mouse_handler.js | 18 +++++++-------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/lib/ace/lib/event.js b/lib/ace/lib/event.js index 42ed97ff..aad5ddd4 100644 --- a/lib/ace/lib/event.js +++ b/lib/ace/lib/event.js @@ -184,32 +184,41 @@ exports.addMouseWheelListener = function(el, callback) { exports.addListener(el, "mousewheel", listener); }; -exports.addMultiMouseDownListener = function(el, button, count, timeout, callback) { +exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbackName) { var clicks = 0; - var startX, startY; + var startX, startY, timer; + var eventNames = { + 2: "dblclick", + 3: "tripleclick", + 4: "quadclick" + }; var listener = function(e) { - clicks += 1; + if (exports.getButton(e) != 0) { + clicks = 0; + } else { + var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5; + + if (!timer || isNewClick) + clicks = 0; + + clicks += 1; + + if (timer) + clearTimeout(timer) + timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600); + } if (clicks == 1) { startX = e.clientX; startY = e.clientY; - - setTimeout(function() { - clicks = 0; - }, timeout || 600); } - var isButton = exports.getButton(e) == button; - if (!isButton || Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5) - clicks = 0; + eventHandler[callbackName]("mousedown", e); - if (clicks == count) { + if (clicks > 4) clicks = 0; - callback(e); - } - - if (isButton) - return exports.preventDefault(e); + else if (clicks > 1) + return eventHandler[callbackName](eventNames[clicks], e); }; exports.addListener(el, "mousedown", listener); diff --git a/lib/ace/mouse/mouse_handler.js b/lib/ace/mouse/mouse_handler.js index f7dbee99..ad9b19f4 100644 --- a/lib/ace/mouse/mouse_handler.js +++ b/lib/ace/mouse/mouse_handler.js @@ -57,12 +57,9 @@ var MouseHandler = function(editor) { }); 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; @@ -126,8 +123,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) { @@ -139,8 +137,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() { @@ -149,8 +149,6 @@ var MouseHandler = function(editor) { event.capture(this.editor.container, onMouseSelection, onMouseSelectionEnd); var timerId = setInterval(onSelectionInterval, 20); - - ev.preventDefault(); }; }).call(MouseHandler.prototype); From e501394c95d02d75fbb90ed4d6d0b8115ea4145d Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 26 May 2012 00:49:35 +0400 Subject: [PATCH 20/40] fix #780 and add tests for background_tokenizer --- lib/ace/background_tokenizer.js | 5 +- lib/ace/background_tokenizer_test.js | 92 ++++++++++++++++++++++++++++ lib/ace/test/all_browser.js | 1 + 3 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 lib/ace/background_tokenizer_test.js diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index 6e2ef93f..6ef3cebe 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -240,12 +240,9 @@ var BackgroundTokenizer = function(tokenizer, editor) { var data = this.tokenizer.getLineTokens(line, state); if (overflow) { data.tokens.push(overflow); - data.state = null; + data.state = "start"; } - if (data.state == "start" && this.states[row] == null) - this.states[row] = "start"; - if (this.states[row] !== data.state) { this.states[row] = data.state; this.lines[row + 1] = null; diff --git a/lib/ace/background_tokenizer_test.js b/lib/ace/background_tokenizer_test.js new file mode 100644 index 00000000..192d1f2b --- /dev/null +++ b/lib/ace/background_tokenizer_test.js @@ -0,0 +1,92 @@ +/* ***** 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 + * + * 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 JavaScriptMode = require("./mode/javascript").Mode; +var Range = require("./range").Range; +var assert = require("./test/assertions"); + +function forceTokenize(session){ + for (var i = 0, l = session.getLength(); i < l; i++) + session.getTokens(i) +} + +function testStates(session, states) { + for (var i = 0, l = session.getLength(); i < l; i++) + assert.equal(session.bgTokenizer.states[i], states[i]) + assert.ok(l == states.length) +} + +module.exports = { + + "test background tokenizer update on session change" : function() { + var doc = new EditSession([ + "/*", + "*/", + "var juhu" + ]); + doc.setMode("ace/mode/javascript") + + forceTokenize(doc) + testStates(doc, ["comment", "start", "start"]) + + doc.remove(new Range(0,2,1,2)) + testStates(doc, [null, "start"]) + + forceTokenize(doc) + testStates(doc, ["comment", "comment"]) + + doc.insert({row:0, column:2}, "\n*/") + testStates(doc, [undefined, undefined, "comment"]) + + forceTokenize(doc) + testStates(doc, ["comment", "start", "start"]) + } +}; + +}); + +if (typeof module !== "undefined" && module === require.main) { + require("asyncjs").test.testcase(module.exports).exec() +} diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index b9987b69..934149e4 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -11,6 +11,7 @@ var log = document.getElementById("log") var testNames = [ "ace/anchor_test", + "ace/background_tokenizer_test", "ace/commands/command_manager_test", "ace/document_test", "ace/edit_session_test", From d2dfec41eea853baf3ce6909e15135d756ca3981 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 26 May 2012 22:03:41 +0400 Subject: [PATCH 21/40] fix highlighting of multiline php strings --- lib/ace/mode/php_highlight_rules.js | 46 ++++++++++++++++------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/lib/ace/mode/php_highlight_rules.js b/lib/ace/mode/php_highlight_rules.js index e25dddc8..424dbfe3 100644 --- a/lib/ace/mode/php_highlight_rules.js +++ b/lib/ace/mode/php_highlight_rules.js @@ -948,18 +948,12 @@ var PhpHighlightRules = function() { token : "string.regexp", regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/][gimy]*\\s*(?=[).,;]|$)" }, { - token : "string", // single line - regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' - }, { - token : "string", // multi line string start - regex : '["][\\s\\S]*', + token : "string", // " string start + regex : '"', next : "qqstring" }, { - token : "string", // single line - regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" - }, { - token : "string", // multi line string start - regex : "['][\\s\\S]+", + token : "string", // ' string start + regex : "'", next : "qstring" }, { token : "constant.numeric", // hex @@ -1040,33 +1034,45 @@ var PhpHighlightRules = function() { ], "qqstring" : [ { + token : "constant.language.escape", + regex : '\\\\(?:[nrtvef\\\\"$]|[0-7]{1,3}|x[0-9A-Fa-f]{1,2})' + }, { + token : "constant.language.escape", + regex : /\$[\w\d]+(?:\[[\w\d]+\])?/ + }, { + token : "constant.language.escape", + regex : /\$\{[^"\}]+\}?/ // this is wrong but ok for now + }, { token : "string", regex : '"', next : "start" }, { token : "string", - regex : '[^"]+' + regex : '.+?' } ], "qstring" : [ { + token : "constant.language.escape", + regex : "\\\\['\\\\]" + }, { token : "string", regex : "'", next : "start" }, { token : "string", - regex : "[^']+" + regex : ".+?" } ], "htmlcomment" : [ - { - token : "comment", - regex : ".*?-->", - next : "start" - }, { - token : "comment", - regex : ".+" - } + { + token : "comment", + regex : ".*?-->", + next : "start" + }, { + token : "comment", + regex : ".+" + } ], "htmltag" : [ { From c8706415065ae87751d2f58ca1c7f6718f1715e5 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 26 May 2012 22:22:40 +0400 Subject: [PATCH 22/40] improve json syntax highlighting --- lib/ace/mode/json_highlight_rules.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/ace/mode/json_highlight_rules.js b/lib/ace/mode/json_highlight_rules.js index 8e4dbdcf..5a039869 100644 --- a/lib/ace/mode/json_highlight_rules.js +++ b/lib/ace/mode/json_highlight_rules.js @@ -49,8 +49,12 @@ var JsonHighlightRules = function() { this.$rules = { "start" : [ { + token : "variable", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)' + }, { token : "string", // single line - regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + regex : '"', + next : "string" }, { token : "constant.numeric", // hex regex : "0[xX][0-9a-fA-F]+\\b" @@ -76,6 +80,26 @@ var JsonHighlightRules = function() { token : "text", regex : "\\s+" } + ], + "string" : [ + { + token : "constant.language.escape", + regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/ + }, { + token : "string", + regex : '[^"\\\\]+', + merge : true + }, { + token : "string", + regex : '"', + next : "start", + merge : true + }, { + token : "string", + regex : "", + next : "start", + merge : true + } ] }; From 3f3769c80db3876e4a0d4f6dd4a26b4b931b5fd1 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 26 May 2012 23:51:19 +0400 Subject: [PATCH 23/40] add diff mode --- demo/kitchen-sink/demo.js | 2 + demo/kitchen-sink/docs/diff.diff | 69 +++++++++++++++++ lib/ace/mode/diff.js | 91 ++++++++++++++++++++++ lib/ace/mode/diff_highlight_rules.js | 108 +++++++++++++++++++++++++++ 4 files changed, 270 insertions(+) create mode 100644 demo/kitchen-sink/docs/diff.diff create mode 100644 lib/ace/mode/diff.js create mode 100644 lib/ace/mode/diff_highlight_rules.js diff --git a/demo/kitchen-sink/demo.js b/demo/kitchen-sink/demo.js index fcf5732f..845d7804 100644 --- a/demo/kitchen-sink/demo.js +++ b/demo/kitchen-sink/demo.js @@ -101,6 +101,7 @@ var modes = [ new Mode("haxe", "haXe", ["hx"]), new Mode("html", "HTML", ["html", "htm"]), new Mode("java", "Java", ["java"]), + new Mode("diff", "Diff", ["diff", "patch"]), new Mode("javascript", "JavaScript", ["js"]), new Mode("json", "JSON", ["json"]), new Mode("latex", "LaTeX", ["tex"]), @@ -165,6 +166,7 @@ var docs = { "docs/plaintext.txt": {name: "Plain Text", prepare: makeHuge, wrapped: true}, "docs/coffeescript.coffee": "Coffeescript", "docs/json.json": "JSON", + "docs/diff.diff": "Diff", "docs/css.css": "CSS", "docs/scss.scss": "SCSS", "docs/less.less": "LESS", diff --git a/demo/kitchen-sink/docs/diff.diff b/demo/kitchen-sink/docs/diff.diff new file mode 100644 index 00000000..3f58128a --- /dev/null +++ b/demo/kitchen-sink/docs/diff.diff @@ -0,0 +1,69 @@ +diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js +index 23fc3fc..ed3b273 100644 +--- a/lib/ace/edit_session.js ++++ b/lib/ace/edit_session.js +@@ -51,6 +51,7 @@ var TextMode = require("./mode/text").Mode; + var Range = require("./range").Range; + var Document = require("./document").Document; + var BackgroundTokenizer = require("./background_tokenizer").BackgroundTokenizer; ++var SearchHighlight = require("./search_highlight").SearchHighlight; + + /** + * class EditSession +@@ -307,6 +308,13 @@ var EditSession = function(text, mode) { + return token; + }; + ++ this.highlight = function(re) { ++ if (!this.$searchHighlight) { ++ var highlight = new SearchHighlight(null, "ace_selected_word", "text"); ++ this.$searchHighlight = this.addDynamicMarker(highlight); ++ } ++ this.$searchHighlight.setRegexp(re); ++ } + /** + * EditSession.setUndoManager(undoManager) + * - undoManager (UndoManager): The new undo manager +@@ -556,7 +564,8 @@ var EditSession = function(text, mode) { + type : type || "line", + renderer: typeof type == "function" ? type : null, + clazz : clazz, +- inFront: !!inFront ++ inFront: !!inFront, ++ id: id + } + + if (inFront) { +diff --git a/lib/ace/editor.js b/lib/ace/editor.js +index 834e603..b27ec73 100644 +--- a/lib/ace/editor.js ++++ b/lib/ace/editor.js +@@ -494,7 +494,7 @@ var Editor = function(renderer, session) { + * Emitted when a selection has changed. + **/ + this.onSelectionChange = function(e) { +- var session = this.getSession(); ++ var session = this.session; + + if (session.$selectionMarker) { + session.removeMarker(session.$selectionMarker); +@@ -509,12 +509,40 @@ var Editor = function(renderer, session) { + this.$updateHighlightActiveLine(); + } + +- var self = this; +- if (this.$highlightSelectedWord && !this.$wordHighlightTimer) +- this.$wordHighlightTimer = setTimeout(function() { +- self.session.$mode.highlightSelection(self); +- self.$wordHighlightTimer = null; +- }, 30, this); ++ var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp() + }; +diff --git a/lib/ace/search_highlight.js b/lib/ace/search_highlight.js +new file mode 100644 +index 0000000..b2df779 +--- /dev/null ++++ b/lib/ace/search_highlight.js +@@ -0,0 +1,3 @@ ++new ++empty file \ No newline at end of file diff --git a/lib/ace/mode/diff.js b/lib/ace/mode/diff.js new file mode 100644 index 00000000..9795f79d --- /dev/null +++ b/lib/ace/mode/diff.js @@ -0,0 +1,91 @@ +/* ***** 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 oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; +var HighlightRules = require("./diff_highlight_rules").DiffHighlightRules; + +var Mode = function() { + this.$tokenizer = new Tokenizer(new HighlightRules().getRules(), "i"); + this.foldingRules = new FoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + +}).call(Mode.prototype); + +exports.Mode = Mode; + + +// folding +var BaseFoldMode = require("./folding/fold_mode").FoldMode; +var Range = require("../range").Range; + +var FoldMode = exports.FoldMode = function() {}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /^(diff|index|@@|\+{3}|\*{5})/; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var line = session.getLine(row); + var start = {row: row, column: line.length - 2}; + + var regList = ["diff", "index", "\\+{3}", "@@|\\*{5}"]; + for (var i = 1; i <= regList.length; i++) { + var re = RegExp("^(" + regList.slice(0, i).join("|") + ")"); + if (re.test(line)) + break; + } + + for (var l = session.getLength(); ++row < l; ) { + line = session.getLine(row); + if (re.test(line)) + break + } + + return Range.fromPoints(start, {row: row - 1, column: line.length}); + }; + +}).call(FoldMode.prototype); + +}); diff --git a/lib/ace/mode/diff_highlight_rules.js b/lib/ace/mode/diff_highlight_rules.js new file mode 100644 index 00000000..eb38a1d3 --- /dev/null +++ b/lib/ace/mode/diff_highlight_rules.js @@ -0,0 +1,108 @@ +/* ***** 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 oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var DiffHighlightRules = function() { + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + + this.$rules = { + "start" : [{ + "regex": "^(?:\\*{15}|={67}|-{3}|\\+{3})$", + "token": "punctuation.definition.separator.diff", + "name": "keyword" + }, { //diff.range.unified + "regex": "^(@@)(\\s*.+?\\s*)(@@)(.*)$", + "token": [ + "constant", + "constant.numeric", + "constant", + "comment.doc.tag" + ] + }, { //diff.range.normal + "regex": "^(\\d+)([,\\d]+)(a|d|c)(\\d+)([,\\d]+)(.*)$", + "token": [ + "constant.numeric", + "punctuation.definition.range.diff", + "constant.function", + "constant.numeric", + "punctuation.definition.range.diff", + "invalid" + ], + "name": "meta." + }, { + "regex": "^(?:(\\-{3}|\\+{3}|\\*{3})( .+))$", + "token": [ + "constant.numeric", + "meta.tag" + ] + }, { // added + "regex": "^([!+>])(.*?)(\\s*)$", + "token": [ + "support.constant", + "text", + "invalid" + ], + }, { // removed + "regex": "^([<\\-])(.*?)(\\s*)$", + "token": [ + "support.function", + "string", + "invalid" + ], + }, { + "regex": "^(diff)( .+)$", + "token": ["keyword", "string.regex"] + }, { + "regex": "^Index .+$", + "token": "variable" + }, { + "regex": "^(.*?)(\\s*)$", + "token": ["invisible", "invalid"] + } + ] + }; +}; + +oop.inherits(DiffHighlightRules, TextHighlightRules); + +exports.DiffHighlightRules = DiffHighlightRules; +}); From 6ccfb6e439d785b4e0b0b162be58083ffad4d5c3 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 27 May 2012 14:50:30 +0400 Subject: [PATCH 24/40] tweak diff mode --- lib/ace/mode/diff.js | 37 +------------- lib/ace/mode/diff_highlight_rules.js | 6 +-- lib/ace/mode/folding/diff.js | 76 ++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 38 deletions(-) create mode 100644 lib/ace/mode/folding/diff.js diff --git a/lib/ace/mode/diff.js b/lib/ace/mode/diff.js index 9795f79d..2e383764 100644 --- a/lib/ace/mode/diff.js +++ b/lib/ace/mode/diff.js @@ -41,10 +41,11 @@ var oop = require("../lib/oop"); var TextMode = require("./text").Mode; var Tokenizer = require("../tokenizer").Tokenizer; var HighlightRules = require("./diff_highlight_rules").DiffHighlightRules; +var FoldMode = require("./folding/diff").FoldMode; var Mode = function() { this.$tokenizer = new Tokenizer(new HighlightRules().getRules(), "i"); - this.foldingRules = new FoldMode(); + this.foldingRules = new FoldMode(["diff", "index", "\\+{3}", "@@|\\*{5}"], "i"); }; oop.inherits(Mode, TextMode); @@ -54,38 +55,4 @@ oop.inherits(Mode, TextMode); exports.Mode = Mode; - -// folding -var BaseFoldMode = require("./folding/fold_mode").FoldMode; -var Range = require("../range").Range; - -var FoldMode = exports.FoldMode = function() {}; -oop.inherits(FoldMode, BaseFoldMode); - -(function() { - - this.foldingStartMarker = /^(diff|index|@@|\+{3}|\*{5})/; - - this.getFoldWidgetRange = function(session, foldStyle, row) { - var line = session.getLine(row); - var start = {row: row, column: line.length - 2}; - - var regList = ["diff", "index", "\\+{3}", "@@|\\*{5}"]; - for (var i = 1; i <= regList.length; i++) { - var re = RegExp("^(" + regList.slice(0, i).join("|") + ")"); - if (re.test(line)) - break; - } - - for (var l = session.getLength(); ++row < l; ) { - line = session.getLine(row); - if (re.test(line)) - break - } - - return Range.fromPoints(start, {row: row - 1, column: line.length}); - }; - -}).call(FoldMode.prototype); - }); diff --git a/lib/ace/mode/diff_highlight_rules.js b/lib/ace/mode/diff_highlight_rules.js index eb38a1d3..fbbc282f 100644 --- a/lib/ace/mode/diff_highlight_rules.js +++ b/lib/ace/mode/diff_highlight_rules.js @@ -89,10 +89,10 @@ var DiffHighlightRules = function() { "invalid" ], }, { - "regex": "^(diff)( .+)$", - "token": ["keyword", "string.regex"] + "regex": "^(diff)(\\s+--\\w+)?(.+?)( .+)?$", + "token": ["variable", "variable", "keyword", "variable"] }, { - "regex": "^Index .+$", + "regex": "^Index.+$", "token": "variable" }, { "regex": "^(.*?)(\\s*)$", diff --git a/lib/ace/mode/folding/diff.js b/lib/ace/mode/folding/diff.js new file mode 100644 index 00000000..89bea274 --- /dev/null +++ b/lib/ace/mode/folding/diff.js @@ -0,0 +1,76 @@ +/* ***** 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 + * + * 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 BaseFoldMode = require("./fold_mode").FoldMode; +var Range = require("../../range").Range; + +var FoldMode = exports.FoldMode = function(levels, flag) { + this.regExpList = levels; + this.flag = flag; + this.foldingStartMarker = RegExp("^(" + levels.join("|") + ")", this.flag); +}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + this.getFoldWidgetRange = function(session, foldStyle, row) { + var line = session.getLine(row); + var start = {row: row, column: line.length}; + + var regList = this.regExpList; + for (var i = 1; i <= regList.length; i++) { + var re = RegExp("^(" + regList.slice(0, i).join("|") + ")", this.flag); + if (re.test(line)) + break; + } + + for (var l = session.getLength(); ++row < l; ) { + line = session.getLine(row); + if (re.test(line)) + break + } + if (row == start.row + 1) + return; + return Range.fromPoints(start, {row: row - 1, column: line.length}); + }; + +}).call(FoldMode.prototype); + +}); From 9d0f2e41e8e54ee33f9915c9b387dc32e62923ba Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 30 May 2012 22:45:12 +0400 Subject: [PATCH 25/40] lazy highlighter for selected word --- lib/ace/edit_session.js | 37 ++++++++++- lib/ace/editor.js | 56 +++++++++++------ .../editor_highlight_selected_word_test.js | 51 +++++++-------- lib/ace/layer/marker.js | 5 ++ lib/ace/mode/text.js | 62 ------------------- lib/ace/search.js | 2 +- 6 files changed, 105 insertions(+), 108 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 23fc3fcd..ed3b2736 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -51,6 +51,7 @@ var TextMode = require("./mode/text").Mode; var Range = require("./range").Range; var Document = require("./document").Document; var BackgroundTokenizer = require("./background_tokenizer").BackgroundTokenizer; +var SearchHighlight = require("./search_highlight").SearchHighlight; /** * class EditSession @@ -307,6 +308,13 @@ var EditSession = function(text, mode) { return token; }; + this.highlight = function(re) { + if (!this.$searchHighlight) { + var highlight = new SearchHighlight(null, "ace_selected_word", "text"); + this.$searchHighlight = this.addDynamicMarker(highlight); + } + this.$searchHighlight.setRegexp(re); + } /** * EditSession.setUndoManager(undoManager) * - undoManager (UndoManager): The new undo manager @@ -556,7 +564,8 @@ var EditSession = function(text, mode) { type : type || "line", renderer: typeof type == "function" ? type : null, clazz : clazz, - inFront: !!inFront + inFront: !!inFront, + id: id } if (inFront) { @@ -570,6 +579,30 @@ var EditSession = function(text, mode) { return id; }; + /** + * EditSession.addDynamicMarker(marker) -> {update} + * - marker : object with update method + * - inFront (Boolean): Set to `true` to establish a front marker + * + **/ + this.addDynamicMarker = function(marker, inFront) { + if (!marker.update) + return; + var id = this.$markerId++; + marker.id = id; + marker.inFront = !!inFront; + + if (inFront) { + this.$frontMarkers[id] = marker; + this._emit("changeFrontMarker") + } else { + this.$backMarkers[id] = marker; + this._emit("changeBackMarker") + } + + return marker; + }; + /** * EditSession.removeMarker(markerId) * - markerId (Number): A number representing a marker @@ -1080,7 +1113,7 @@ var EditSession = function(text, mode) { * {:Document.getTextRange.desc} **/ this.getTextRange = function(range) { - return this.doc.getTextRange(range); + return this.doc.getTextRange(range || this.selection.getRange()); }; /** related to: Document.insert diff --git a/lib/ace/editor.js b/lib/ace/editor.js index c238dec4..a8efe242 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -523,7 +523,7 @@ var Editor = function(renderer, session) { * Emitted when a selection has changed. **/ this.onSelectionChange = function(e) { - var session = this.getSession(); + var session = this.session; if (session.$selectionMarker) { session.removeMarker(session.$selectionMarker); @@ -538,12 +538,40 @@ var Editor = function(renderer, session) { this.$updateHighlightActiveLine(); } - var self = this; - if (this.$highlightSelectedWord && !this.$wordHighlightTimer) - this.$wordHighlightTimer = setTimeout(function() { - self.session.$mode.highlightSelection(self); - self.$wordHighlightTimer = null; - }, 30, this); + var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp() + this.session.highlight(re); + }; + + this.$getSelectionHighLightRegexp = function() { + var session = this.session; + + var selection = this.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 re = this.$search.$assembleRegExp({ + wholeWord: true, + caseSensitive: true, + needle: needle + }); + + return re; }; /** @@ -917,7 +945,7 @@ var Editor = function(renderer, session) { this.$highlightSelectedWord = true; /** - * Editor.setHighlightSelectedWord(shouldHighlight) + * Editor.setHighlightSelectedWord(shouldHighlight) * - shouldHighlight (Boolean): Set to `true` to highlight the currently selected word * * Determines if the currently selected word should be highlighted. @@ -927,20 +955,12 @@ var Editor = function(renderer, session) { return; this.$highlightSelectedWord = shouldHighlight; - if (shouldHighlight) { - this.session.getMode().highlightSelection(this); - } else { - this.session.getMode().clearSelectionHighlight(this); - if (this.$wordHighlightTimer) { - clearTimeout(this.$wordHighlightTimer); - this.$wordHighlightTimer = null; - } - } + this.$onSelectionChange(); }; /** * Editor.getHighlightSelectedWord() -> Boolean - * + * * Returns `true` if currently highlighted words are to be highlighted. **/ this.getHighlightSelectedWord = function() { diff --git a/lib/ace/editor_highlight_selected_word_test.js b/lib/ace/editor_highlight_selected_word_test.js index 3cdaddd3..c18a78bb 100644 --- a/lib/ace/editor_highlight_selected_word_test.js +++ b/lib/ace/editor_highlight_selected_word_test.js @@ -70,6 +70,16 @@ var lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + "libero vehicula odio, eget bibendum mauris velit eu lorem.\n" + "consectetur"; +function callHighlighterUpdate(session, firstRow, lastRow) { + var rangeCount = 0; + var mockMarkerLayer = { drawSingleLineMarker: function() {rangeCount++;} } + session.$searchHighlight.update([], mockMarkerLayer, session, { + firstRow: firstRow, + lastRow: lastRow + }); + return rangeCount; +} + module.exports = { setUp: function(next) { this.session = new EditSession(lipsum); @@ -87,55 +97,51 @@ module.exports = { this.editor.moveCursorTo(0, 9); this.selection.selectWord(); - assert.ok(this.editor.$wordHighlightTimer != null); - this.session.$mode.highlightSelection(this.editor); + var highlighter = this.editor.session.$searchHighlight; + assert.ok(highlighter != null); var range = this.selection.getRange(); assert.equal(this.session.getTextRange(range), "ipsum"); - assert.equal(this.session.$selectionOccurrences.length, 1); + assert.equal(highlighter.cache.length, 0); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 2); }, "test: highlight a word and clear highlight": function() { this.editor.moveCursorTo(0, 8); this.selection.selectWord(); - this.session.$mode.highlightSelection(this.editor); var range = this.selection.getRange(); assert.equal(this.session.getTextRange(range), "ipsum"); - assert.equal(this.session.$selectionOccurrences.length, 1); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 2); - this.session.getMode().clearSelectionHighlight(this.editor); - assert.equal(this.session.$selectionOccurrences.length, 0); + this.session.highlight(""); + assert.equal(this.session.$searchHighlight.cache.length, 0); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 0); }, "test: highlight another word": function() { this.selection.moveCursorTo(0, 14); this.selection.selectWord(); - this.session.$mode.highlightSelection(this.editor); var range = this.selection.getRange(); assert.equal(this.session.getTextRange(range), "dolor"); - assert.equal(this.session.$selectionOccurrences.length, 3); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 4); }, "test: no selection, no highlight": function() { this.selection.clearSelection(); - this.session.$mode.highlightSelection(this.editor); - assert.equal(this.session.$selectionOccurrences.length, 0); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 0); }, "test: select a word, no highlight": function() { this.selection.moveCursorTo(0, 14); this.selection.selectWord(); - this.session.$mode.highlightSelection(this.editor); this.editor.setHighlightSelectedWord(false); - assert.ok(this.editor.$wordHighlightTimer == null); - var range = this.selection.getRange(); assert.equal(this.session.getTextRange(range), "dolor"); - assert.equal(this.session.$selectionOccurrences.length, 0); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 0); }, "test: select a word with no matches": function() { @@ -156,32 +162,29 @@ module.exports = { this.search.set(currentOptions); this.selection.setSelectionRange(match); - this.session.$mode.highlightSelection(this.editor); assert.equal(this.session.getTextRange(match), "Mauris"); - assert.equal(this.session.$selectionOccurrences.length, 0); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 1); }, "test: partial word selection 1": function() { this.selection.moveCursorTo(0, 14); this.selection.selectWord(); this.selection.selectLeft(); - this.session.$mode.highlightSelection(this.editor); var range = this.selection.getRange(); assert.equal(this.session.getTextRange(range), "dolo"); - assert.equal(this.session.$selectionOccurrences.length, 0); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 0); }, "test: partial word selection 2": function() { this.selection.moveCursorTo(0, 13); this.selection.selectWord(); this.selection.selectRight(); - this.session.$mode.highlightSelection(this.editor); var range = this.selection.getRange(); assert.equal(this.session.getTextRange(range), "dolor "); - assert.equal(this.session.$selectionOccurrences.length, 0); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 0); }, "test: partial word selection 3": function() { @@ -189,11 +192,10 @@ module.exports = { this.selection.selectWord(); this.selection.selectLeft(); this.selection.shiftSelection(1); - this.session.$mode.highlightSelection(this.editor); var range = this.selection.getRange(); assert.equal(this.session.getTextRange(range), "olor"); - assert.equal(this.session.$selectionOccurrences.length, 0); + assert.equal(callHighlighterUpdate(this.session, 0, 0), 0); }, "test: select last word": function() { @@ -216,10 +218,9 @@ module.exports = { this.search.set(currentOptions); this.selection.setSelectionRange(match); - this.session.$mode.highlightSelection(this.editor); assert.equal(this.session.getTextRange(match), "consectetur"); - assert.equal(this.session.$selectionOccurrences.length, 2); + assert.equal(callHighlighterUpdate(this.session, 0, 1), 3); } }; diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index 990af0ad..f5999338 100644 --- a/lib/ace/layer/marker.js +++ b/lib/ace/layer/marker.js @@ -76,6 +76,11 @@ var Marker = function(parentEl) { for ( var key in this.markers) { var marker = this.markers[key]; + if (!marker.range) { + marker.update(html, this, this.session, config); + continue; + } + var range = marker.range.clipRows(config.firstRow, config.lastRow); if (range.isEmpty()) continue; 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/search.js b/lib/ace/search.js index 38e96ea6..c03391e2 100644 --- a/lib/ace/search.js +++ b/lib/ace/search.js @@ -54,7 +54,7 @@ var Range = require("./range").Range; /** * new Search() * - * Creates a new `Search` object. The following search options ae avaliable: + * Creates a new `Search` object. The following search options are avaliable: * * * needle: string or regular expression * * backwards: false From 5f203ae4f5b4187bf21dca90ef92761191ebc96d Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 30 May 2012 23:30:21 +0400 Subject: [PATCH 26/40] add back forgotten file --- lib/ace/search_highlight.js | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 lib/ace/search_highlight.js diff --git a/lib/ace/search_highlight.js b/lib/ace/search_highlight.js new file mode 100644 index 00000000..b2df7792 --- /dev/null +++ b/lib/ace/search_highlight.js @@ -0,0 +1,87 @@ +/* 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 + * + * 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 lang = require("./lib/lang"); +var oop = require("./lib/oop"); +var Range = require("./range").Range; + +var SearchHighlight = function(regExp, clazz, type) { + this.setRegexp(regExp); + this.clazz = clazz; + this.type = type || "text"; +}; + +(function() { + this.setRegexp = function(regExp) { + if (this.regExp+"" == regExp+"") + return; + this.regExp = regExp; + this.cache = []; + }; + + this.update = function(html, markerLayer, session, config) { + if (!this.regExp) + return; + var start = config.firstRow, end = config.lastRow; + + for (var i = start; i <= end; i++) { + var ranges = this.cache[i]; + if (ranges == null) { + ranges = lang.getMatchOffsets(session.getLine(i), this.regExp); + ranges = ranges.map(function(match) { + return new Range(i, match.offset, i, match.offset + match.length); + }); + this.cache[i] = ranges.length ? ranges : ""; + } + + for (var j = ranges.length; j --; ) { + markerLayer.drawSingleLineMarker( + html, ranges[j].toScreenRange(session), this.clazz, config, + null, this.type + ); + } + } + }; + +}).call(SearchHighlight.prototype); + +exports.SearchHighlight = SearchHighlight; +}); From da94ecdb42b46bd06991a36fdeeb6faa1d0bc882 Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Wed, 30 May 2012 14:34:32 -0700 Subject: [PATCH 27/40] Fix building of themes --- Makefile.dryice.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.dryice.js b/Makefile.dryice.js index da119177..7f68bad7 100755 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -347,14 +347,14 @@ function buildAce(aceProject, options) { });*/ // use this instead, to not create separate modules for js and css var themePath = "lib/ace/theme/" + theme - var js = fs.readFileSync(themePath + ".js", "utf8") - js = js.replace("define(", "define('ace/theme/" + theme + "',") + var js = fs.readFileSync(themePath + ".js", "utf8"); + js = js.replace("define(", "define('ace/theme/" + theme + "', ['require', 'exports', 'module', 'ace/lib/dom'], "); if (fs.existsSync(themePath + ".css", "utf8")) { var css = fs.readFileSync(themePath + ".css", "utf8") js = js.replace(/require\(.ace\/requirejs\/text!.*?\)/, quoteString(css)) } - filters.forEach(function(f) {js = f(js); }) + filters.forEach(function(f) {js = f(js); }); fs.writeFileSync(targetDir + suffix + "/theme-" + theme + ".js", js); }); From 28d4807d09a6b5aed33476e0754500edd368a084 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 31 May 2012 23:10:31 +0400 Subject: [PATCH 28/40] update makefile --- Makefile.dryice.js | 272 ++++++++++++++++++++++++--------------------- 1 file changed, 143 insertions(+), 129 deletions(-) diff --git a/Makefile.dryice.js b/Makefile.dryice.js index 7f68bad7..39fd5b2a 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; @@ -197,7 +191,7 @@ function demo(aceProject) { copy({ source: "kitchen-sink.html", - dest: "build/kitchen-sink.html", + dest: BUILD_DIR + "/kitchen-sink.html", filter: [changeComments, function(data) { return data.replace(/"(demo|build)\//g, "\""); }] @@ -205,14 +199,14 @@ function demo(aceProject) { copy({ source: "demo/kitchen-sink/styles.css", - dest: "build/kitchen-sink/styles.css", + dest: BUILD_DIR + "/kitchen-sink/styles.css", filter: [ changeComments ] }); fs.readdirSync("demo/kitchen-sink/docs/").forEach(function(x) { copy({ source: "demo/kitchen-sink/docs/" + x, - dest: "build/kitchen-sink/docs/" + x + dest: BUILD_DIR + "/kitchen-sink/docs/" + x }); }); @@ -235,22 +229,26 @@ function demo(aceProject) { }); copy({ source: demo, - dest: "build/kitchen-sink/demo.js", + dest: BUILD_DIR + "/kitchen-sink/demo.js", }); - copyFileSync("demo/kitchen-sink/logo.png", "build/kitchen-sink/logo.png"); + copyFileSync("demo/kitchen-sink/logo.png", BUILD_DIR + "/kitchen-sink/logo.png"); } -function buildAce(aceProject, options) { +function buildAce(options) { + var aceProject = { + roots: [ACE_HOME + '/lib', ACE_HOME + '/demo'], + textPluginPattern: /^ace\/requirejs\/text!/ + }; var defaults = { - targetDir: __dirname + "/build/src", + targetDir: BUILD_DIR + "/src", ns: "ace", exportModule: "ace/ace", requires: null, compress: false, noconflict: false, - suffix: "", + suffix: null, name: "ace", modes: fs.readdirSync("lib/ace/mode").map(function(x) { if (x.slice(-3) == ".js" && !/_highlight_rules|_test|_worker|xml_util|_outdent|behaviour/.test(x)) @@ -262,15 +260,29 @@ function buildAce(aceProject, options) { workers: ["javascript", "coffee", "css", "json", "xquery"], keybindings: ["vim", "emacs"] }; + for(var key in defaults) if (!options.hasOwnProperty(key)) options[key] = defaults[key]; + if (options.suffix == null) { + options.suffix = ""; + if (options.compress) + options.suffix += "-min"; + if (options.noconflict) + options.suffix += "-noconflict"; + } + if (!options.requires) options.requires = [options.exportModule]; - var filters = [copy.filter.moduleDefines, filterTextPlugin]; + var filters = [ + copy.filter.moduleDefines, + filterTextPlugin, + removeUseStrict, + removeLicenceCmments + ]; if (options.noconflict) { filters.push(namespace(options.ns)); @@ -280,20 +292,10 @@ function buildAce(aceProject, options) { var exportFilter = exportAce(options.ns, options.exportModule); } - // remove use strict - filters.push(function(text) { - return text.replace(/['"]use strict['"];/g, ""); - }) - // remove redundant comments - filters.push(function(text) { - return text.replace(/(;)\s*\/\*[\d\D]*?\*\//g, "$1"); - }) - if (options.compress) filters.push(copy.filter.uglifyjs); - var suffix = options.suffix; - var targetDir = options.targetDir; + var targetDir = options.targetDir + options.suffix; var name = options.name; var project = copy.createCommonJsProject(aceProject); @@ -304,8 +306,8 @@ function buildAce(aceProject, options) { }); copy({ source: [{ - project: project, - require: options.requires + project: project, + require: options.requires }], filter: [ copy.filter.moduleDefines ], dest: ace @@ -314,7 +316,7 @@ function buildAce(aceProject, options) { copy({ source: ace, filter: exportFilter ? filters.concat(exportFilter) : filters, - dest: targetDir + suffix + '/' + name + ".js" + dest: targetDir + '/' + name + ".js" }); console.log('# ace modes ---------'); @@ -324,11 +326,11 @@ function buildAce(aceProject, options) { console.log("mode " + mode); copy({ source: [{ - project: cloneProject(project), - require: [ 'ace/mode/' + mode ] + project: cloneProject(project), + require: [ 'ace/mode/' + mode ] }], filter: filters, - dest: targetDir + suffix + "/mode-" + mode + ".js" + dest: targetDir + "/mode-" + mode + ".js" }); }); @@ -343,7 +345,7 @@ function buildAce(aceProject, options) { require: ["ace/theme/" + theme] }], filter: filters, - dest: targetDir + suffix + "/theme-" + theme + ".js" + dest: targetDir + "/theme-" + theme + ".js" });*/ // use this instead, to not create separate modules for js and css var themePath = "lib/ace/theme/" + theme @@ -356,43 +358,7 @@ function buildAce(aceProject, options) { } filters.forEach(function(f) {js = f(js); }); - fs.writeFileSync(targetDir + suffix + "/theme-" + theme + ".js", js); - }); - - console.log('# ace worker ---------'); - - options.workers.forEach(function(mode) { - console.log("worker for " + mode + " mode"); - var worker = copy.createDataObject(); - var workerProject = copy.createCommonJsProject({ - roots: [ - ACE_HOME + '/lib' - ], - textPluginPattern: /^ace\/requirejs\/text!/ - }); - copy({ - source: [ - { - project: workerProject, - require: [ - 'ace/lib/fixoldbrowsers', - 'ace/lib/event_emitter', - 'ace/lib/oop', - 'ace/mode/' + mode + '_worker' - ] - } - ], - filter: [ copy.filter.moduleDefines, filterTextPlugin ], - dest: worker - }); - copy({ - source: [ - ACE_HOME + "/lib/ace/worker/worker.js", - worker - ], - filter: [ /* copy.filter.uglifyjs */], - dest: targetDir + "/worker-" + mode + ".js" - }); + fs.writeFileSync(targetDir + "/theme-" + theme + ".js", js); }); console.log('# ace key bindings ---------'); @@ -406,9 +372,49 @@ function buildAce(aceProject, options) { require: [ 'ace/keyboard/' + keybinding ] }], filter: filters, - dest: targetDir + suffix + "/keybinding-" + keybinding + ".js" + dest: targetDir + "/keybinding-" + keybinding + ".js" }); }); + + console.log('# ace worker ---------'); + + filters = [ + copy.filter.moduleDefines, + filterTextPlugin, + removeUseStrict, + removeLicenceCmments + ]; + + options.workers.forEach(function(mode) { + console.log("worker for " + mode + " mode"); + var worker = copy.createDataObject(); + var workerProject = copy.createCommonJsProject({ + roots: [ ACE_HOME + '/lib' ], + textPluginPattern: /^ace\/requirejs\/text!/ + }); + copy({ + source: [{ + project: workerProject, + require: [ + 'ace/lib/fixoldbrowsers', + 'ace/lib/event_emitter', + 'ace/lib/oop', + 'ace/mode/' + mode + '_worker' + ] + }], + filter: filters, + dest: worker + }); + copy({ + source: [ + ACE_HOME + "/lib/ace/worker/worker.js", + worker + ], + filter: options.compress ? [copy.filter.uglifyjs] : [], + dest: targetDir + "/worker-" + mode + ".js" + }); + }); + } // TODO: replace with project.clone once it is fixed in dryice @@ -459,6 +465,14 @@ function filterTextPlugin(text) { return text.replace(/(['"])ace\/requirejs\/text\!/g, "$1text!"); } +function removeUseStrict(text) { + return text.replace(/['"]use strict['"];/g, ""); +} + +function removeLicenceCmments(text) { + return text.replace(/(;)\s*\/\*[\d\D]*?\*\//g, "$1"); +} + function namespace(ns) { return function(text) { text = text From a1f79bb2e2ca0944960cce9ec99cf60a43f84d1e Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 31 May 2012 23:40:11 +0400 Subject: [PATCH 29/40] update readme and demo --- Makefile.dryice.js | 12 +-- Readme.md | 62 +++++---------- demo/kitchen-sink/demo.js | 154 +++++++++++++++++++------------------- index.html | 2 +- kitchen-sink.html | 18 +++-- 5 files changed, 113 insertions(+), 135 deletions(-) diff --git a/Makefile.dryice.js b/Makefile.dryice.js index 39fd5b2a..547c5b1a 100755 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -176,14 +176,10 @@ function demo() { } var changeComments = function(data) { return (data - .replace("DEVEL-->", "") - .replace("", "") - .replace(" + + + + + + - + + +
@@ -216,8 +226,7 @@
- - + - +