From bd2e5381ccaf1f803ebc433daecb8b6a6efb13c0 Mon Sep 17 00:00:00 2001 From: Chester Wood Date: Fri, 4 Jan 2013 17:34:12 -0700 Subject: [PATCH 01/11] Add keybinding selection to textarea bookmarklet --- lib/ace/ext/textarea.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/ace/ext/textarea.js b/lib/ace/ext/textarea.js index a8f6317f..85db6ef0 100644 --- a/lib/ace/ext/textarea.js +++ b/lib/ace/ext/textarea.js @@ -324,6 +324,19 @@ function setupApi(editor, editorDiv, settingDiv, ace, options, loader) { editorDiv.style.fontSize = value; break; + case "keybindings": + switch (value) { + case "vim": + editor.setKeyboardHandler(require("ace/keyboard/vim").handler); + break; + case "emacs": + editor.setKeyboardHandler(require("ace/keyboard/emacs").handler); + break; + default: + editor.setKeyboardHandler(null); + } + break; + case "softWrap": switch (value) { case "off": @@ -391,6 +404,7 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) { theme: "Theme:", fontSize: "Font Size:", softWrap: "Soft Wrap:", + keybindings: "Keyboard", showPrintMargin: "Show Print Margin:", useSoftTabs: "Use Soft Tabs:", showInvisibles: "Show Invisibles" @@ -456,6 +470,11 @@ function setupSettingPanel(settingDiv, settingOpener, editor, options) { 80: "80", free: "Free" }, + keybindings: { + ace: "ace", + vim: "vim", + emacs: "emacs" + }, showPrintMargin: BOOL, useSoftTabs: BOOL, showInvisibles: BOOL @@ -518,6 +537,7 @@ exports.options = { gutter: "false", fontSize: "12px", softWrap: "off", + keybindings: "ace", showPrintMargin: "false", useSoftTabs: "true", showInvisibles: "true" From d7ff50c9fe1791aa24201bc37b5458cd84ce4c25 Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 7 Jan 2013 23:04:01 +0400 Subject: [PATCH 02/11] fix cursor in emacs mode --- lib/ace/keyboard/emacs.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index 8fc3aeeb..2952b80a 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -33,14 +33,14 @@ define(function(require, exports, module) { var dom = require("../lib/dom"); -var screenToTextBlockCoordinates = function(pageX, pageY) { +var screenToTextBlockCoordinates = function(x, y) { var canvasPos = this.scroller.getBoundingClientRect(); var col = Math.floor( - (pageX + this.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft()) / this.characterWidth + (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth ); var row = Math.floor( - (pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop()) / this.lineHeight + (y + this.scrollTop - canvasPos.top) / this.lineHeight ); return this.session.screenToDocumentPosition(row, col); From 66d8e37f4d17c6ac7241ec4f9ac438bb604aeba2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 3 Dec 2012 12:30:21 +0400 Subject: [PATCH 03/11] async loading of fonts in demo --- kitchen-sink.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kitchen-sink.html b/kitchen-sink.html index ac241fa1..858514f9 100644 --- a/kitchen-sink.html +++ b/kitchen-sink.html @@ -13,13 +13,13 @@ - + @@ -280,4 +280,4 @@ PACKAGE--> - \ No newline at end of file + From ffadbe44bfde74827122eeed01673b92d9bd8f69 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 6 Dec 2012 00:22:42 +0400 Subject: [PATCH 04/11] add config.loadModule --- lib/ace/config.js | 31 ++++++++++++++++++++ lib/ace/edit_session.js | 56 ++++++++++++------------------------- lib/ace/virtual_renderer.js | 23 ++------------- 3 files changed, 51 insertions(+), 59 deletions(-) diff --git a/lib/ace/config.js b/lib/ace/config.js index 5a1b0e47..d2d2aea7 100644 --- a/lib/ace/config.js +++ b/lib/ace/config.js @@ -32,6 +32,8 @@ define(function(require, exports, module) { "no use strict"; var lang = require("./lib/lang"); +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; var global = (function() { return this; @@ -65,6 +67,9 @@ exports.all = function() { return lang.copyObject(options); }; +// module loading +oop.implement(exports, EventEmitter); + exports.moduleUrl = function(name, component) { if (options.$moduleUrls[name]) return options.$moduleUrls[name]; @@ -87,6 +92,32 @@ exports.setModuleUrl = function(name, subst) { return options.$moduleUrls[name] = subst; }; +exports.loadModule = function(moduleName, onLoad) { + var module, moduleType; + if (Array.isArray(moduleName)) { + moduleType = moduleName[0]; + moduleName = moduleName[1]; + } + try { + module = require(moduleName); + } catch (e) {}; + if (module) + return onLoad(module); + + var afterLoad = function() { + require([moduleName], function(module) { + exports._emit("load.module", {name: moduleName, module: module}); + onLoad(module); + }); + }; + + if (!exports.get("packaged")) + return afterLoad(); + net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad); +}; + + +// initialization exports.init = function() { options.packaged = require.packaged || module.packaged || (global.define && define.packaged); diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index ae16984b..7efdcade 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -898,49 +898,27 @@ var EditSession = function(text, mode) { }; this.$modes = {}; - this._loadMode = function(mode, callback) { + this._loadMode = function(name, callback) { if (!this.$modes["null"]) this.$modes["null"] = this.$modes["ace/mode/text"] = new TextMode(); - if (this.$modes[mode]) - return callback(this.$modes[mode]); + if (this.$modes[name]) + return callback(this.$modes[name]); var _self = this; - var module; - try { - module = require(mode); - } catch (e) {}; - // sometimes require returns empty object (this bug is present in requirejs 2 as well) - if (module && module.Mode) - return done(module); + config.loadModule(["mode", name], function(module) { + if (_self.$modes[name]) + return callback(_self.$modes[name]); + if (module && module.Mode) { + _self.$modes[name] = new module.Mode(); + _self.$modes[name].$id = name; + callback(_self.$modes[name]); + } + }); // set mode to text until loading is finished if (!this.$mode) this.$setModePlaceholder(); - - fetch(mode, function() { - require([mode], done); - }); - - function done(module) { - if (_self.$modes[mode]) - return callback(_self.$modes[mode]); - - _self.$modes[mode] = new module.Mode(); - _self.$modes[mode].$id = mode; - _self._emit("loadmode", { - name: mode, - mode: _self.$modes[mode] - }); - callback(_self.$modes[mode]); - } - - function fetch(name, callback) { - if (!config.get("packaged")) - return callback(); - - net.loadScript(config.moduleUrl(name, "mode"), callback); - } }; this.$setModePlaceholder = function() { @@ -982,11 +960,13 @@ var EditSession = function(text, mode) { if (_self.$modeId !== mode) return; - _self.setMode(module); + _self.$onChangeMode(module); }); - return; - } - + } else + _self.$onChangeMode(module); + } + + this.$onChangeMode = function(mode) { if (this.$mode === mode) return; this.$mode = mode; this.$modeId = mode.$id; diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 4661768b..ef70133a 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -1278,10 +1278,7 @@ var VirtualRenderer = function(container, theme) { }; this._loadTheme = function(name, callback) { - if (!config.get("packaged")) - return callback(); - - net.loadScript(config.moduleUrl(name, "theme"), callback); + }; /** @@ -1292,28 +1289,12 @@ var VirtualRenderer = function(container, theme) { **/ this.setTheme = function(theme) { var _self = this; - this.$themeValue = theme; _self._dispatchEvent('themeChange',{theme:theme}); if (!theme || typeof theme == "string") { var moduleName = theme || "ace/theme/textmate"; - - var module; - try { - module = require(moduleName); - } catch (e) {}; - if (module) - return afterLoad(module); - - _self._loadTheme(moduleName, function() { - require([moduleName], function(module) { - if (_self.$themeValue !== theme) - return; - - afterLoad(module); - }); - }); + config.loadModule(["theme", moduleName], afterLoad); } else { afterLoad(theme); } From e6671462cda18173a92f6c299cacb1c5b0c7bf61 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 6 Dec 2012 15:55:21 +0400 Subject: [PATCH 05/11] cleanup mode loading --- lib/ace/edit_session.js | 53 +++++++++++++---------------------------- 1 file changed, 17 insertions(+), 36 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 7efdcade..52dc7789 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -918,27 +918,9 @@ var EditSession = function(text, mode) { // set mode to text until loading is finished if (!this.$mode) - this.$setModePlaceholder(); + this.$onChangeMode(_self.$modes["ace/mode/text"], true); }; - this.$setModePlaceholder = function() { - this.$mode = this.$modes["null"]; - var tokenizer = this.$mode.getTokenizer(); - - if (!this.bgTokenizer) { - this.bgTokenizer = new BackgroundTokenizer(tokenizer); - var _self = this; - this.bgTokenizer.addEventListener("update", function(e) { - _self._emit("tokenizerUpdate", e); - }); - } else { - this.bgTokenizer.setTokenizer(tokenizer); - } - this.bgTokenizer.setDocument(this.getDocument()); - - this.tokenRe = this.$mode.tokenRe; - this.nonTokenRe = this.$mode.nonTokenRe; - }; /** * Sets a new text mode for the `EditSession`. This method also emits the `'changeMode'` event. If a [[BackgroundTokenizer `BackgroundTokenizer`]] is set, the `'tokenizerUpdate'` event is also emitted. @@ -948,25 +930,22 @@ var EditSession = function(text, mode) { this.$mode = null; this.$modeId = null; this.setMode = function(mode) { - mode = mode || "null"; // load on demand - if (typeof mode === "string") { - if (this.$modeId == mode) + if (!mode || typeof mode === "string") { + var modeName = mode || "ace/mode/text"; + if (this.$modeId === modeName) return; - this.$modeId = mode; - var _self = this; - this._loadMode(mode, function(module) { - if (_self.$modeId !== mode) - return; - - _self.$onChangeMode(module); - }); + this.$modeId = modeName; + this._loadMode(modeName, function(mode) { + if (this.$modeId === modeName) + this.$onChangeMode(mode); + }.bind(this)); } else - _self.$onChangeMode(module); - } + this.$onChangeMode(mode); + }; - this.$onChangeMode = function(mode) { + this.$onChangeMode = function(mode, $isPlaceholder) { if (this.$mode === mode) return; this.$mode = mode; this.$modeId = mode.$id; @@ -994,14 +973,16 @@ var EditSession = function(text, mode) { } this.bgTokenizer.setDocument(this.getDocument()); - this.bgTokenizer.start(0); this.tokenRe = mode.tokenRe; this.nonTokenRe = mode.nonTokenRe; - this.$setFolding(mode.foldingRules); - this._emit("changeMode"); + if (!$isPlaceholder) { + this.$setFolding(mode.foldingRules); + this._emit("changeMode"); + this.bgTokenizer.start(0); + } }; From dcbbeb7e228e707d711807a280fff48fa5d58cc3 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 6 Dec 2012 15:54:42 +0400 Subject: [PATCH 06/11] enable seting keybindings by name --- demo/kitchen-sink/demo.js | 11 ++++------- lib/ace/editor.js | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/demo/kitchen-sink/demo.js b/demo/kitchen-sink/demo.js index ce5d57ad..93859a61 100644 --- a/demo/kitchen-sink/demo.js +++ b/demo/kitchen-sink/demo.js @@ -46,8 +46,6 @@ var theme = require("ace/theme/textmate"); var EditSession = require("ace/edit_session").EditSession; var UndoManager = require("ace/undomanager").UndoManager; -var vim = require("ace/keyboard/vim").handler; -var emacs = require("ace/keyboard/emacs").handler; var HashHandler = require("ace/keyboard/hash_handler").HashHandler; var Renderer = require("ace/virtual_renderer").VirtualRenderer; @@ -162,11 +160,10 @@ commands.addCommand({ exec: function() {alert("Fake Save File");} }); -var keybindings = { - // Null = use "default" keymapping - ace: null, - vim: vim, - emacs: emacs, +var keybindings = { + ace: null, // Null = use "default" keymapping + vim: require("ace/keyboard/vim").handler, + emacs: "ace/keyboard/emacs", // This is a way to define simple keyboard remappings custom: new HashHandler({ "gotoright": "Tab", diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 865de51f..44bfb36a 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -46,6 +46,7 @@ var Range = require("./range").Range; var EventEmitter = require("./lib/event_emitter").EventEmitter; var CommandManager = require("./commands/command_manager").CommandManager; var defaultCommands = require("./commands/default_commands").commands; +var config = require("./config"); /** * @@ -100,7 +101,17 @@ var Editor = function(renderer, session) { * **/ this.setKeyboardHandler = function(keyboardHandler) { - this.keyBinding.setKeyboardHandler(keyboardHandler); + if (typeof keyboardHandler == "string" && keyboardHandler) { + this.$keybindingId = keyboardHandler; + var _self = this; + config.loadModule(["keybinding", keyboardHandler], function(module) { + if (_self.$keybindingId == keyboardHandler) + _self.keyBinding.setKeyboardHandler(module && module.handler); + }); + } else { + delete this.$keybindingId; + this.keyBinding.setKeyboardHandler(keyboardHandler); + } }; /** @@ -2149,4 +2160,4 @@ var Editor = function(renderer, session) { exports.Editor = Editor; -}); \ No newline at end of file +}); From 0a61c37a3bc62c7293d4fff1025556ffe584d6f4 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 12 Dec 2012 13:43:13 +0400 Subject: [PATCH 07/11] add options to php mode --- lib/ace/mode/php.js | 7 +++++-- lib/ace/mode/php_highlight_rules.js | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/ace/mode/php.js b/lib/ace/mode/php.js index a73f3e84..6312840d 100644 --- a/lib/ace/mode/php.js +++ b/lib/ace/mode/php.js @@ -35,14 +35,17 @@ var oop = require("../lib/oop"); var TextMode = require("./text").Mode; var Tokenizer = require("../tokenizer").Tokenizer; var PhpHighlightRules = require("./php_highlight_rules").PhpHighlightRules; +var PhpLangHighlightRules = require("./php_highlight_rules").PhpLangHighlightRules; var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; var Range = require("../range").Range; var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var unicode = require("../unicode"); -var Mode = function() { - this.$tokenizer = new Tokenizer(new PhpHighlightRules().getRules()); +var Mode = function(opts) { + var inline = opts && opts.inline; + var HighlightRules = inline ? PhpLangHighlightRules : PhpHighlightRules; + this.$tokenizer = new Tokenizer(new HighlightRules().getRules()); this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); this.foldingRules = new CStyleFoldMode(); diff --git a/lib/ace/mode/php_highlight_rules.js b/lib/ace/mode/php_highlight_rules.js index dc08198d..eac9ecea 100644 --- a/lib/ace/mode/php_highlight_rules.js +++ b/lib/ace/mode/php_highlight_rules.js @@ -1062,4 +1062,5 @@ var PhpHighlightRules = function() { oop.inherits(PhpHighlightRules, HtmlHighlightRules); exports.PhpHighlightRules = PhpHighlightRules; +exports.PhpLangHighlightRules = PhpLangHighlightRules; }); From 07792dab9a61cba95607fd395db5f0a91387a29c Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 15 Dec 2012 16:42:51 +0400 Subject: [PATCH 08/11] allow options object in setMode --- lib/ace/edit_session.js | 72 ++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 52dc7789..bf0c0a51 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -898,29 +898,6 @@ var EditSession = function(text, mode) { }; this.$modes = {}; - this._loadMode = function(name, callback) { - if (!this.$modes["null"]) - this.$modes["null"] = this.$modes["ace/mode/text"] = new TextMode(); - - if (this.$modes[name]) - return callback(this.$modes[name]); - - var _self = this; - config.loadModule(["mode", name], function(module) { - if (_self.$modes[name]) - return callback(_self.$modes[name]); - if (module && module.Mode) { - _self.$modes[name] = new module.Mode(); - _self.$modes[name].$id = name; - callback(_self.$modes[name]); - } - }); - - // set mode to text until loading is finished - if (!this.$mode) - this.$onChangeMode(_self.$modes["ace/mode/text"], true); - }; - /** * Sets a new text mode for the `EditSession`. This method also emits the `'changeMode'` event. If a [[BackgroundTokenizer `BackgroundTokenizer`]] is set, the `'tokenizerUpdate'` event is also emitted. @@ -930,21 +907,44 @@ var EditSession = function(text, mode) { this.$mode = null; this.$modeId = null; this.setMode = function(mode) { - // load on demand - if (!mode || typeof mode === "string") { - var modeName = mode || "ace/mode/text"; - if (this.$modeId === modeName) - return; + if (mode && typeof mode === "object") { + if (mode.getTokenizer) + return this.$onChangeMode(mode); + var options = mode; + var path = options.path; + } else { + path = mode || "ace/mode/text"; + } - this.$modeId = modeName; - this._loadMode(modeName, function(mode) { - if (this.$modeId === modeName) - this.$onChangeMode(mode); - }.bind(this)); - } else - this.$onChangeMode(mode); + // this is needed if ace isn't on require path (e.g tests in node) + if (!this.$modes["ace/mode/text"]) + this.$modes["ace/mode/text"] = new TextMode(); + + if (this.$modes[path] && !options) + return this.$onChangeMode(this.$modes[path]); + + // load on demand + this.$modeId = path; + config.loadModule(["mode", path], function(m) { + if (this.$modeId !== path) + return; + if (this.$modes[path] && !options) + return this.$onChangeMode(this.$modes[path]); + if (m && m.Mode) { + m = new m.Mode(options); + if (!options) { + this.$modes[path] = m; + m.$id = path; + } + this.$onChangeMode(m) + } + }.bind(this)); + + // set mode to text until loading is finished + if (!this.$mode) + this.$onChangeMode(this.$modes["ace/mode/text"], true); }; - + this.$onChangeMode = function(mode, $isPlaceholder) { if (this.$mode === mode) return; this.$mode = mode; From 51a91e71af68c94b67d40f4c0684ce815d60a23c Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 18 Dec 2012 22:16:22 +0400 Subject: [PATCH 09/11] make container argument of VirtualRenderer optional --- lib/ace/virtual_renderer.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index ef70133a..8f169def 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -69,16 +69,16 @@ dom.importCssString(editorCss, "ace_editor"); var VirtualRenderer = function(container, theme) { var _self = this; - this.container = container; + this.container = container || dom.createElement("div"); // TODO: this breaks rendering in Cloud9 with multiple ace instances -// // Imports CSS once per DOM document ('ace_editor' serves as an identifier). -// dom.importCssString(editorCss, "ace_editor", container.ownerDocument); + // // 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; - dom.addCssClass(container, "ace_editor"); + dom.addCssClass(this.container, "ace_editor"); this.setTheme(theme); @@ -113,7 +113,7 @@ var VirtualRenderer = function(container, theme) { this.$animatedScroll = false; - this.scrollBar = new ScrollBar(container); + this.scrollBar = new ScrollBar(this.container); this.scrollBar.addEventListener("scroll", function(e) { if (!_self.$inScrollAnimation) _self.session.setScrollTop(e.data); From b9a220de96b1b82124b8dac78e53a6f409b7b4a1 Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 7 Jan 2013 23:17:23 +0400 Subject: [PATCH 10/11] use delayed loading of keybindings for ext/textarea --- lib/ace/ext/textarea.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ace/ext/textarea.js b/lib/ace/ext/textarea.js index 85db6ef0..a36db850 100644 --- a/lib/ace/ext/textarea.js +++ b/lib/ace/ext/textarea.js @@ -327,10 +327,10 @@ function setupApi(editor, editorDiv, settingDiv, ace, options, loader) { case "keybindings": switch (value) { case "vim": - editor.setKeyboardHandler(require("ace/keyboard/vim").handler); + editor.setKeyboardHandler("ace/keyboard/vim"); break; case "emacs": - editor.setKeyboardHandler(require("ace/keyboard/emacs").handler); + editor.setKeyboardHandler("ace/keyboard/emacs"); break; default: editor.setKeyboardHandler(null); From 575646f230d08ed9cff3e7658dfc09d1c14af345 Mon Sep 17 00:00:00 2001 From: nightwing Date: Mon, 7 Jan 2013 23:23:31 +0400 Subject: [PATCH 11/11] readme must show build status of master branch --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 63d028da..5e9e3107 100644 --- a/Readme.md +++ b/Readme.md @@ -163,6 +163,6 @@ Continuous Integration status ----------------------------- This project is tested with [Travis CI](http://travis-ci.org) -[![Build Status](https://secure.travis-ci.org/ajaxorg/ace.png)](http://travis-ci.org/ajaxorg/ace) +[![Build Status](https://secure.travis-ci.org/ajaxorg/ace.png?branch=master)](http://travis-ci.org/ajaxorg/ace)