From 0d9b5dd8b9f72f43037dc7176e0ef318edbe803a Mon Sep 17 00:00:00 2001 From: c-spencer Date: Sat, 21 May 2011 16:58:45 +0100 Subject: [PATCH 01/16] Add transformInput and transformRemove hooks into edit modes --- lib/ace/editor.js | 21 +++++++++++++++++++-- lib/ace/mode/text.js | 10 +++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index ef9b0e8a..a32ff85e 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -412,6 +412,11 @@ var Editor =function(renderer, session) { var mode = session.getMode(); var cursor = this.getCursorPosition(); + var transform = mode.transformInput(session.getState(cursor.row), this, session, text); + + if (transform) + text = transform.text; + text = text.replace("\t", this.session.getTabString()); // remove selected text @@ -427,12 +432,19 @@ var Editor =function(renderer, session) { this.clearSelection(); + var start = cursor.column; var lineState = session.getState(cursor.row); var shouldOutdent = mode.checkOutdent(lineState, session.getLine(cursor.row), text); var line = session.getLine(cursor.row); var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString()); var end = session.insert(cursor, text); - + + if (transform && transform.selection) { + this.selection.setSelectionRange( + new Range(cursor.row, start + transform.selection[0], + cursor.row, start + transform.selection[1])); + } + var lineState = session.getState(cursor.row); // TODO disabled multiline auto indent @@ -600,8 +612,13 @@ var Editor =function(renderer, session) { if (this.selection.isEmpty()) this.selection.selectLeft(); + + var session = this.session; + var selection = this.getSelectionRange(); + var state = session.getState(selection.start.row); + var range = session.getMode().transformRemove(state, this, session, selection); - this.session.remove(this.getSelectionRange()); + this.session.remove(range); this.clearSelection(); }; diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index d0a3e495..70a3739c 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -150,7 +150,7 @@ var Mode = function() { this.$modes[this.$embeds[i]] = new mapping[this.$embeds[i]](); } - var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent']; + var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformInput', 'transformRemove']; for (var i = 0; i < delegations.length; i++) { (function(scope) { @@ -178,6 +178,14 @@ var Mode = function() { return defaultHandler ? defaultHandler.apply(this, args) : undefined; }; + + this.transformInput = function(state, editor, session, text) { + return false; + }; + + this.transformRemove = function(state, editor, session, range) { + return range; + }; }).call(Mode.prototype); From 1261c55913f633b41e76474ee3e1bdb1fe866750 Mon Sep 17 00:00:00 2001 From: c-spencer Date: Sat, 21 May 2011 18:43:40 +0100 Subject: [PATCH 02/16] Mode Behaviours --- lib/ace/editor.js | 2 +- lib/ace/mode/text.js | 61 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index a32ff85e..14422369 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -412,7 +412,7 @@ var Editor =function(renderer, session) { var mode = session.getMode(); var cursor = this.getCursorPosition(); - var transform = mode.transformInput(session.getState(cursor.row), this, session, text); + var transform = mode.transformInsert(session.getState(cursor.row), this, session, text); if (transform) text = transform.text; diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index 70a3739c..819b45aa 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -179,11 +179,70 @@ var Mode = function() { return defaultHandler ? defaultHandler.apply(this, args) : undefined; }; - this.transformInput = function(state, editor, session, text) { + this.addBehaviour = function (name, insert, remove) { + if (this.$behaviours === undefined) { + this.$behaviours = {}; + } + this.$behaviours[name] = { + insert: insert, + remove: remove + }; + } + + this.removeBehaviour = function (name) { + if (this.$behaviours && this.$behaviours[name]) { + delete this.$behaviours[name]; + } + } + + this.inheritBehaviours = function (mode) { + if (typeof mode === "function") { + var behaviours = new mode().getBehaviours(); + } else { + var behaviours = mode.getBehaviours(); + } + for (var key in behaviours) { + if (behaviours.hasOwnProperty(key)) { + this.addBehaviour(key, behaviours[key].insert, behaviours[key].remove); + } + } + } + + this.getBehaviours = function (filter) { + if (!filter) { + return this.$behaviours; + } else { + var ret = {} + for (var i = 0; i < filter.length; i++) { + if (this.$behaviours[filter[i]]) { + ret[filter[i]] = this.$behaviours[filter[i]]; + } + } + return ret; + } + } + + this.transformInsert = function(state, editor, session, text) { + for (var key in this.$behaviours) { + if (this.$behaviours.hasOwnProperty(key)) { + var ret = this.$behaviours[key].insert.apply(this, arguments); + if (ret !== false) { + return ret; + } + } + } return false; }; this.transformRemove = function(state, editor, session, range) { + for (var key in this.$behaviours) { + if (this.$behaviours.hasOwnProperty(key)) { + var ret = this.$behaviours[key].remove.apply(this, arguments); + if (ret !== false) { + return ret; + } + } + } return range; }; From 3cdfa374278b24e51b8f005e2bad07926fce64c2 Mon Sep 17 00:00:00 2001 From: c-spencer Date: Sun, 22 May 2011 00:27:22 +0100 Subject: [PATCH 03/16] Factor out mode transforms into Behaviour --- lib/ace/editor.js | 17 +++- lib/ace/mode/behaviour.js | 101 +++++++++++++++++++ lib/ace/mode/behaviour/cstyle.js | 166 +++++++++++++++++++++++++++++++ lib/ace/mode/javascript.js | 2 + lib/ace/mode/text.js | 82 +++++---------- 5 files changed, 306 insertions(+), 62 deletions(-) create mode 100644 lib/ace/mode/behaviour.js create mode 100644 lib/ace/mode/behaviour/cstyle.js diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 14422369..4b1fdd29 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -412,8 +412,9 @@ var Editor =function(renderer, session) { var mode = session.getMode(); var cursor = this.getCursorPosition(); - var transform = mode.transformInsert(session.getState(cursor.row), this, session, text); + // Get a transform if the current mode wants one. + var transform = mode.transformInsert(session.getState(cursor.row), this, session, text); if (transform) text = transform.text; @@ -440,9 +441,17 @@ var Editor =function(renderer, session) { var end = session.insert(cursor, text); if (transform && transform.selection) { - this.selection.setSelectionRange( - new Range(cursor.row, start + transform.selection[0], - cursor.row, start + transform.selection[1])); + if (transform.selection.length == 2) { // Transform relative to the current column + this.selection.setSelectionRange( + new Range(cursor.row, start + transform.selection[0], + cursor.row, start + transform.selection[1])); + } else { // Transform relative to the current row. + this.selection.setSelectionRange( + new Range(cursor.row + transform.selection[0], + transform.selection[1], + cursor.row + transform.selection[2], + transform.selection[3])); + } } var lineState = session.getState(cursor.row); diff --git a/lib/ace/mode/behaviour.js b/lib/ace/mode/behaviour.js new file mode 100644 index 00000000..46886a21 --- /dev/null +++ b/lib/ace/mode/behaviour.js @@ -0,0 +1,101 @@ +/* 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): + * Chris Spencer + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +var Behaviour = function() { + this.$behaviours = {}; +}; + +(function () { + + this.add = function (name, insert, remove) { + if (this.$behaviours === undefined) { + this.$behaviours = {}; + } + this.$behaviours[name] = { + insert: insert, + remove: remove + }; + } + + this.addBehaviours = function (behaviours) { + for (var key in behaviours) { + if (behaviours.hasOwnProperty(key)) { + this.addBehaviour(key, behaviours[key].insert, behaviours[key].remove); + } + } + } + + this.remove = function (name) { + if (this.$behaviours && this.$behaviours[name]) { + delete this.$behaviours[name]; + } + } + + this.inherit = function (mode) { + if (typeof mode === "function") { + var behaviours = new mode().getBehaviours(); + } else { + var behaviours = mode.getBehaviours(); + } + for (var key in behaviours) { + if (behaviours.hasOwnProperty(key)) { + this.add(key, behaviours[key].insert, behaviours[key].remove); + } + } + } + + this.getBehaviours = function (filter) { + if (!filter) { + return this.$behaviours; + } else { + var ret = {} + for (var i = 0; i < filter.length; i++) { + if (this.$behaviours[filter[i]]) { + ret[filter[i]] = this.$behaviours[filter[i]]; + } + } + return ret; + } + } + +}).call(Behaviour.prototype); + +exports.Behaviour = Behaviour; +}); \ No newline at end of file diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js new file mode 100644 index 00000000..56a77581 --- /dev/null +++ b/lib/ace/mode/behaviour/cstyle.js @@ -0,0 +1,166 @@ +/* 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): + * Chris Spencer + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +var oop = require("pilot/oop"); +var Behaviour = require('ace/mode/behaviour').Behaviour; + +var CstyleBehaviour = function () { + + this.add("brace_insert", function (state, editor, session, text) { + if (text == '{') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: '{' + selected + '}', + selection: false + } + } else { + return { + text: '{}', + selection: [1,1] + } + } + } else if (text == '}') { // This should do some matching checks + var cursor = editor.getCursorPosition(); + var rightChar = session.doc.getLine(cursor.row).substring(cursor.column, cursor.column+1); + if (rightChar == '}') { + return { + text: '', + selection: [1,1] + } + } + } else if (text == "\n") { + var cursor = editor.getCursorPosition(); + var rightChar = session.doc.getLine(cursor.row).substring(cursor.column, cursor.column+1); + if (rightChar == '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column}); + + var indent = this.getNextLineIndent(state, session.doc.getLine(cursor.row).substring(0, session.doc.getLine(cursor.row).length-1), " "); + var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row)); + + return { + text: '\n'+indent+'\n'+next_indent, + selection: [1,indent.length,1,indent.length] + } + } + } + return false; + }, function (state, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + var rightChar = session.doc.getLine(range.start.row).substring(range.start.column+1, range.start.column+2); + if (rightChar == '}') { + return new Range(range.start.row, range.start.column, range.start.row, range.end.column+1); + } + } + return false; + }); + + this.add("parens_insert", function (state, editor, session, text) { + if (text == '(') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: '(' + selected + ')', + selection: false + } + } else { + return { + text: '()', + selection: [1,1] + } + } + } else if (text == ')') { // This should do some matching checks + var cursor = editor.getCursorPosition(); + var rightChar = session.doc.getLine(cursor.row).substring(cursor.column, cursor.column+1); + if (rightChar == ')') { + return { + text: '', + selection: [1,1] + } + } + } + return false; + }, function (state, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + var rightChar = session.doc.getLine(range.start.row).substring(range.start.column+1, range.start.column+2); + if (rightChar == ')') { + return new Range(range.start.row, range.start.column, range.start.row, range.end.column+1); + } + } + return false; + }); + + this.add("string_dquotes", function (state, editor, session, text) { + if (text == '"') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return { + text: '"' + selected + '"', + selection: false + } + } else { + return { + text: '""', + selection: [1,1] + } + } + } + return false; + }, function (state, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '"') { + var rightChar = session.doc.getLine(range.start.row).substring(range.start.column+1, range.start.column+2); + if (rightChar == '"') { + return new Range(range.start.row, range.start.column, range.start.row, range.end.column+1); + } + } + return false; + }); + +} +oop.inherits(CstyleBehaviour, Behaviour); + +exports.CstyleBehaviour = CstyleBehaviour; +}); \ No newline at end of file diff --git a/lib/ace/mode/javascript.js b/lib/ace/mode/javascript.js index a7634bf6..f7b934fa 100644 --- a/lib/ace/mode/javascript.js +++ b/lib/ace/mode/javascript.js @@ -44,10 +44,12 @@ var JavaScriptHighlightRules = require("ace/mode/javascript_highlight_rules").Ja var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent; var Range = require("ace/range").Range; var WorkerClient = require("ace/worker/worker_client").WorkerClient; +var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour; var Mode = function() { this.$tokenizer = new Tokenizer(new JavaScriptHighlightRules().getRules()); this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); }; oop.inherits(Mode, TextMode); diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index 819b45aa..620364a7 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -22,6 +22,7 @@ * Contributor(s): * Fabian Jakobs * Mihai Sucan + * Chris Spencer * * 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 @@ -41,9 +42,11 @@ define(function(require, exports, module) { var Tokenizer = require("ace/tokenizer").Tokenizer; var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules; +var Behaviour = require("ace/mode/behaviour").Behaviour; var Mode = function() { this.$tokenizer = new Tokenizer(new TextHighlightRules().getRules()); + this.$behaviour = new Behaviour(); }; (function() { @@ -150,7 +153,7 @@ var Mode = function() { this.$modes[this.$embeds[i]] = new mapping[this.$embeds[i]](); } - var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformInput', 'transformRemove']; + var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformInsert', 'transformRemove']; for (var i = 0; i < delegations.length; i++) { (function(scope) { @@ -179,69 +182,32 @@ var Mode = function() { return defaultHandler ? defaultHandler.apply(this, args) : undefined; }; - this.addBehaviour = function (name, insert, remove) { - if (this.$behaviours === undefined) { - this.$behaviours = {}; - } - this.$behaviours[name] = { - insert: insert, - remove: remove - }; - } - - this.removeBehaviour = function (name) { - if (this.$behaviours && this.$behaviours[name]) { - delete this.$behaviours[name]; - } - } - - this.inheritBehaviours = function (mode) { - if (typeof mode === "function") { - var behaviours = new mode().getBehaviours(); - } else { - var behaviours = mode.getBehaviours(); - } - for (var key in behaviours) { - if (behaviours.hasOwnProperty(key)) { - this.addBehaviour(key, behaviours[key].insert, behaviours[key].remove); - } - } - } - - this.getBehaviours = function (filter) { - if (!filter) { - return this.$behaviours; - } else { - var ret = {} - for (var i = 0; i < filter.length; i++) { - if (this.$behaviours[filter[i]]) { - ret[filter[i]] = this.$behaviours[filter[i]]; - } - } - return ret; - } - } - this.transformInsert = function(state, editor, session, text) { - for (var key in this.$behaviours) { - if (this.$behaviours.hasOwnProperty(key)) { - var ret = this.$behaviours[key].insert.apply(this, arguments); - if (ret !== false) { - return ret; - } - } + if (this.$behaviour) { + var behaviours = this.$behaviour.getBehaviours(); + for (var key in behaviours) { + if (behaviours.hasOwnProperty(key)) { + var ret = behaviours[key].insert.apply(this, arguments); + if (ret !== false) { + return ret; + } + } + } } return false; }; this.transformRemove = function(state, editor, session, range) { - for (var key in this.$behaviours) { - if (this.$behaviours.hasOwnProperty(key)) { - var ret = this.$behaviours[key].remove.apply(this, arguments); - if (ret !== false) { - return ret; - } - } + if (this.$behaviour) { + var behaviours = this.$behaviour.getBehaviours(); + for (var key in behaviours) { + if (behaviours.hasOwnProperty(key)) { + var ret = behaviours[key].remove.apply(this, arguments); + if (ret !== false) { + return ret; + } + } + } } return range; }; From 6fcff0f691230dc19f8f239e2e63c07fcaa7b3ba Mon Sep 17 00:00:00 2001 From: c-spencer Date: Sun, 22 May 2011 01:44:12 +0100 Subject: [PATCH 04/16] Add C-style behaviours to C/Csharp/Java/PHP --- lib/ace/mode/c_cpp.js | 2 ++ lib/ace/mode/csharp.js | 2 ++ lib/ace/mode/java.js | 2 ++ lib/ace/mode/php.js | 2 ++ 4 files changed, 8 insertions(+) diff --git a/lib/ace/mode/c_cpp.js b/lib/ace/mode/c_cpp.js index 08bd249e..958aed92 100644 --- a/lib/ace/mode/c_cpp.js +++ b/lib/ace/mode/c_cpp.js @@ -44,10 +44,12 @@ var Tokenizer = require("ace/tokenizer").Tokenizer; var c_cppHighlightRules = require("ace/mode/c_cpp_highlight_rules").c_cppHighlightRules; var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent; var Range = require("ace/range").Range; +var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour; var Mode = function() { this.$tokenizer = new Tokenizer(new c_cppHighlightRules().getRules()); this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); }; oop.inherits(Mode, TextMode); diff --git a/lib/ace/mode/csharp.js b/lib/ace/mode/csharp.js index 1d164340..472e775f 100644 --- a/lib/ace/mode/csharp.js +++ b/lib/ace/mode/csharp.js @@ -5,10 +5,12 @@ var TextMode = require("ace/mode/text").Mode; var Tokenizer = require("ace/tokenizer").Tokenizer; var CSharpHighlightRules = require("ace/mode/csharp_highlight_rules").CSharpHighlightRules; var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent; +var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour; var Mode = function() { this.$tokenizer = new Tokenizer(new CSharpHighlightRules().getRules()); this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); }; oop.inherits(Mode, TextMode); diff --git a/lib/ace/mode/java.js b/lib/ace/mode/java.js index 6014398f..ac3c942a 100644 --- a/lib/ace/mode/java.js +++ b/lib/ace/mode/java.js @@ -5,10 +5,12 @@ var JavaScriptMode = require("ace/mode/javascript").Mode; var Tokenizer = require("ace/tokenizer").Tokenizer; var JavaHighlightRules = require("ace/mode/java_highlight_rules").JavaHighlightRules; var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent; +var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour; var Mode = function() { this.$tokenizer = new Tokenizer(new JavaHighlightRules().getRules()); this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); }; oop.inherits(Mode, JavaScriptMode); diff --git a/lib/ace/mode/php.js b/lib/ace/mode/php.js index 13fdf30b..a11a7c49 100644 --- a/lib/ace/mode/php.js +++ b/lib/ace/mode/php.js @@ -43,10 +43,12 @@ var Tokenizer = require("ace/tokenizer").Tokenizer; var PhpHighlightRules = require("ace/mode/php_highlight_rules").PhpHighlightRules; var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent; var Range = require("ace/range").Range; +var CstyleBehaviour = require("ace/mode/behaviour/cstyle").CstyleBehaviour; var Mode = function() { this.$tokenizer = new Tokenizer(new PhpHighlightRules().getRules()); this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); }; oop.inherits(Mode, TextMode); From 138ec94f531e7b4a3425fd54361d2ecf5f78b9d9 Mon Sep 17 00:00:00 2001 From: c-spencer Date: Sun, 22 May 2011 02:53:30 +0100 Subject: [PATCH 05/16] Style improvements --- lib/ace/mode/behaviour/cstyle.js | 43 +++++++++++++++++++------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index 56a77581..dd432ea6 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -55,30 +55,32 @@ var CstyleBehaviour = function () { } else { return { text: '{}', - selection: [1,1] + selection: [1, 1] } } } else if (text == '}') { // This should do some matching checks var cursor = editor.getCursorPosition(); - var rightChar = session.doc.getLine(cursor.row).substring(cursor.column, cursor.column+1); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); if (rightChar == '}') { return { text: '', - selection: [1,1] + selection: [1, 1] } } } else if (text == "\n") { var cursor = editor.getCursorPosition(); - var rightChar = session.doc.getLine(cursor.row).substring(cursor.column, cursor.column+1); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); if (rightChar == '}') { var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column}); - - var indent = this.getNextLineIndent(state, session.doc.getLine(cursor.row).substring(0, session.doc.getLine(cursor.row).length-1), " "); + + var indent = this.getNextLineIndent(state, line.substring(0, line.length - 1), session.getTabString()); var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row)); return { - text: '\n'+indent+'\n'+next_indent, - selection: [1,indent.length,1,indent.length] + text: '\n' + indent + '\n' + next_indent, + selection: [1, indent.length, 1, indent.length] } } } @@ -86,9 +88,11 @@ var CstyleBehaviour = function () { }, function (state, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '{') { - var rightChar = session.doc.getLine(range.start.row).substring(range.start.column+1, range.start.column+2); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); if (rightChar == '}') { - return new Range(range.start.row, range.start.column, range.start.row, range.end.column+1); + return new Range(range.start.row, range.start.column, + range.start.row, range.end.column + 1); } } return false; @@ -106,16 +110,17 @@ var CstyleBehaviour = function () { } else { return { text: '()', - selection: [1,1] + selection: [1, 1] } } } else if (text == ')') { // This should do some matching checks var cursor = editor.getCursorPosition(); - var rightChar = session.doc.getLine(cursor.row).substring(cursor.column, cursor.column+1); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); if (rightChar == ')') { return { text: '', - selection: [1,1] + selection: [1, 1] } } } @@ -123,9 +128,11 @@ var CstyleBehaviour = function () { }, function (state, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '(') { - var rightChar = session.doc.getLine(range.start.row).substring(range.start.column+1, range.start.column+2); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); if (rightChar == ')') { - return new Range(range.start.row, range.start.column, range.start.row, range.end.column+1); + return new Range(range.start.row, range.start.column, + range.start.row, range.end.column + 1); } } return false; @@ -151,9 +158,11 @@ var CstyleBehaviour = function () { }, function (state, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '"') { - var rightChar = session.doc.getLine(range.start.row).substring(range.start.column+1, range.start.column+2); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); if (rightChar == '"') { - return new Range(range.start.row, range.start.column, range.start.row, range.end.column+1); + return new Range(range.start.row, range.start.column, + range.start.row, range.end.column + 1); } } return false; From 8e7f4f2716aef74d188d78278c6d8afe0b0a5c95 Mon Sep 17 00:00:00 2001 From: c-spencer Date: Sun, 22 May 2011 02:59:28 +0100 Subject: [PATCH 06/16] Allow mode behaviours to be disabled at the editor level --- lib/ace/editor.js | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 4b1fdd29..098e2750 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -413,10 +413,12 @@ var Editor =function(renderer, session) { var cursor = this.getCursorPosition(); - // Get a transform if the current mode wants one. - var transform = mode.transformInsert(session.getState(cursor.row), this, session, text); - if (transform) - text = transform.text; + if (this.getBehavioursEnabled()) { + // Get a transform if the current mode wants one. + var transform = mode.transformInsert(session.getState(cursor.row), this, session, text); + if (transform) + text = transform.text; + } text = text.replace("\t", this.session.getTabString()); @@ -603,6 +605,15 @@ var Editor =function(renderer, session) { this.getReadOnly = function() { return this.$readOnly; }; + + this.$modeBehaviours = true; + this.setBehavioursEnabled = function (enabled) { + this.$modeBehaviours = enabled; + } + + this.getBehavioursEnabled = function () { + return this.$modeBehaviours; + } this.removeRight = function() { if (this.$readOnly) @@ -622,10 +633,12 @@ var Editor =function(renderer, session) { if (this.selection.isEmpty()) this.selection.selectLeft(); - var session = this.session; - var selection = this.getSelectionRange(); - var state = session.getState(selection.start.row); - var range = session.getMode().transformRemove(state, this, session, selection); + var range = this.getSelectionRange(); + if (this.getBehavioursEnabled()) { + var session = this.session; + var state = session.getState(range.start.row); + range = session.getMode().transformRemove(state, this, session, range); + } this.session.remove(range); this.clearSelection(); From deb5a01693036bbdaf2e112fbaf44e5973ea5da9 Mon Sep 17 00:00:00 2001 From: c-spencer Date: Sun, 22 May 2011 13:27:36 +0100 Subject: [PATCH 07/16] Improved Cstyle behaviour --- lib/ace/mode/behaviour/cstyle.js | 60 ++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index dd432ea6..801f81da 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -58,14 +58,17 @@ var CstyleBehaviour = function () { selection: [1, 1] } } - } else if (text == '}') { // This should do some matching checks + } else if (text == '}') { var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); var rightChar = line.substring(cursor.column, cursor.column + 1); if (rightChar == '}') { - return { - text: '', - selection: [1, 1] + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null) { + return { + text: '', + selection: [1, 1] + } } } } else if (text == "\n") { @@ -113,14 +116,17 @@ var CstyleBehaviour = function () { selection: [1, 1] } } - } else if (text == ')') { // This should do some matching checks + } else if (text == ')') { var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); var rightChar = line.substring(cursor.column, cursor.column + 1); if (rightChar == ')') { - return { - text: '', - selection: [1, 1] + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null) { + return { + text: '', + selection: [1, 1] + } } } } @@ -148,9 +154,41 @@ var CstyleBehaviour = function () { selection: false } } else { - return { - text: '""', - selection: [1,1] + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + + // We're escaped. + if (leftChar == '\\') { + return false; + } + + // Find what token we're inside. + var tokens = session.getTokens(selection.start.row, selection.start.row)[0].tokens; + var col = 0, token; + for (var x in tokens) { + token = tokens[x].type; + if ((tokens[x].value.length + col) > selection.start.column) { + break; + } + col += tokens[x].value.length; + } + + // Try and be smart about when we auto insert. + if (token === "text" || !token || (token !== "comment" && selection.end.column === line.length)) { + return { + text: '""', + selection: [1,1] + } + } else if (token === "string") { + // Ignore input and move right one if we're typing over the closing quote. + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '"') { + return { + text: '', + selection: [1, 1] + } + } } } } From bc45a8892853fcce3ee905dc88b159e5cff32944 Mon Sep 17 00:00:00 2001 From: c-spencer Date: Sun, 22 May 2011 14:34:01 +0100 Subject: [PATCH 08/16] Make behavioural actions easily extensible --- lib/ace/editor.js | 7 ++++-- lib/ace/mode/behaviour.js | 26 ++++++++++----------- lib/ace/mode/behaviour/cstyle.js | 18 ++++++++++----- lib/ace/mode/text.js | 39 ++++++++++---------------------- 4 files changed, 42 insertions(+), 48 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 098e2750..4b6a3538 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -415,7 +415,7 @@ var Editor =function(renderer, session) { if (this.getBehavioursEnabled()) { // Get a transform if the current mode wants one. - var transform = mode.transformInsert(session.getState(cursor.row), this, session, text); + var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text); if (transform) text = transform.text; } @@ -637,7 +637,10 @@ var Editor =function(renderer, session) { if (this.getBehavioursEnabled()) { var session = this.session; var state = session.getState(range.start.row); - range = session.getMode().transformRemove(state, this, session, range); + var new_range = session.getMode().transformAction(state, 'deletion', this, session, range); + if (new_range !== false) { + range = new_range; + } } this.session.remove(range); diff --git a/lib/ace/mode/behaviour.js b/lib/ace/mode/behaviour.js index 46886a21..6b57d3d3 100644 --- a/lib/ace/mode/behaviour.js +++ b/lib/ace/mode/behaviour.js @@ -44,20 +44,24 @@ var Behaviour = function() { (function () { - this.add = function (name, insert, remove) { - if (this.$behaviours === undefined) { - this.$behaviours = {}; + this.add = function (name, action, callback) { + switch (undefined) { + case this.$behaviours: + this.$behaviours = {}; + case this.$behaviours[name]: + this.$behaviours[name] = {}; } - this.$behaviours[name] = { - insert: insert, - remove: remove - }; + this.$behaviours[name][action] = callback; } this.addBehaviours = function (behaviours) { for (var key in behaviours) { if (behaviours.hasOwnProperty(key)) { - this.addBehaviour(key, behaviours[key].insert, behaviours[key].remove); + for (var action in behaviours[key]) { + if (behaviours[key].hasOwnProperty(action)) { + this.add(key, action, behaviours[key][action]); + } + } } } } @@ -74,11 +78,7 @@ var Behaviour = function() { } else { var behaviours = mode.getBehaviours(); } - for (var key in behaviours) { - if (behaviours.hasOwnProperty(key)) { - this.add(key, behaviours[key].insert, behaviours[key].remove); - } - } + this.addBehaviours(behaviours); } this.getBehaviours = function (filter) { diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index 801f81da..cbbbb283 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -43,7 +43,7 @@ var Behaviour = require('ace/mode/behaviour').Behaviour; var CstyleBehaviour = function () { - this.add("brace_insert", function (state, editor, session, text) { + this.add("braces", "insertion", function (state, action, editor, session, text) { if (text == '{') { var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); @@ -88,7 +88,9 @@ var CstyleBehaviour = function () { } } return false; - }, function (state, editor, session, range) { + }); + + this.add("braces", "deletion", function (state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '{') { var line = session.doc.getLine(range.start.row); @@ -101,7 +103,7 @@ var CstyleBehaviour = function () { return false; }); - this.add("parens_insert", function (state, editor, session, text) { + this.add("parens", "insertion", function (state, action, editor, session, text) { if (text == '(') { var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); @@ -131,7 +133,9 @@ var CstyleBehaviour = function () { } } return false; - }, function (state, editor, session, range) { + }); + + this.add("parens", "deletion", function (state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '(') { var line = session.doc.getLine(range.start.row); @@ -144,7 +148,7 @@ var CstyleBehaviour = function () { return false; }); - this.add("string_dquotes", function (state, editor, session, text) { + this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { if (text == '"') { var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); @@ -193,7 +197,9 @@ var CstyleBehaviour = function () { } } return false; - }, function (state, editor, session, range) { + }); + + this.add("string_dquotes", "deletion", function (state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '"') { var line = session.doc.getLine(range.start.row); diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index 620364a7..7e2e96a2 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -153,7 +153,7 @@ var Mode = function() { this.$modes[this.$embeds[i]] = new mapping[this.$embeds[i]](); } - var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformInsert', 'transformRemove']; + var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformAction']; for (var i = 0; i < delegations.length; i++) { (function(scope) { @@ -182,36 +182,21 @@ var Mode = function() { return defaultHandler ? defaultHandler.apply(this, args) : undefined; }; - this.transformInsert = function(state, editor, session, text) { + this.transformAction = function(state, action, editor, session, param) { if (this.$behaviour) { - var behaviours = this.$behaviour.getBehaviours(); - for (var key in behaviours) { - if (behaviours.hasOwnProperty(key)) { - var ret = behaviours[key].insert.apply(this, arguments); - if (ret !== false) { - return ret; - } - } - } + var behaviours = this.$behaviour.getBehaviours(); + for (var key in behaviours) { + if (behaviours.hasOwnProperty(key) && behaviours[key][action]) { + var ret = behaviours[key][action].apply(this, arguments); + if (ret !== false) { + return ret; + } + } + } } return false; - }; + } - this.transformRemove = function(state, editor, session, range) { - if (this.$behaviour) { - var behaviours = this.$behaviour.getBehaviours(); - for (var key in behaviours) { - if (behaviours.hasOwnProperty(key)) { - var ret = behaviours[key].remove.apply(this, arguments); - if (ret !== false) { - return ret; - } - } - } - } - return range; - }; - }).call(Mode.prototype); exports.Mode = Mode; From d9e7970d2abf311718c4b49e85593a4ef4ad90dc Mon Sep 17 00:00:00 2001 From: c-spencer Date: Wed, 25 May 2011 16:56:40 +0100 Subject: [PATCH 09/16] Improve string behaviour, start on Xml behaviours, disable behaviours by default --- lib/ace/editor.js | 2 +- lib/ace/mode/behaviour.js | 6 ++--- lib/ace/mode/behaviour/cstyle.js | 17 +++++++++---- lib/ace/mode/behaviour/xml.js | 41 ++++++++++++++++++++++++++++++++ lib/ace/mode/xml.js | 2 ++ 5 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 lib/ace/mode/behaviour/xml.js diff --git a/lib/ace/editor.js b/lib/ace/editor.js index ea8ff9d4..f15024db 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -611,7 +611,7 @@ var Editor =function(renderer, session) { return this.$readOnly; }; - this.$modeBehaviours = true; + this.$modeBehaviours = false; this.setBehavioursEnabled = function (enabled) { this.$modeBehaviours = enabled; } diff --git a/lib/ace/mode/behaviour.js b/lib/ace/mode/behaviour.js index 6b57d3d3..6c145d22 100644 --- a/lib/ace/mode/behaviour.js +++ b/lib/ace/mode/behaviour.js @@ -72,11 +72,11 @@ var Behaviour = function() { } } - this.inherit = function (mode) { + this.inherit = function (mode, filter) { if (typeof mode === "function") { - var behaviours = new mode().getBehaviours(); + var behaviours = new mode().getBehaviours(filter); } else { - var behaviours = mode.getBehaviours(); + var behaviours = mode.getBehaviours(filter); } this.addBehaviours(behaviours); } diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index cbbbb283..d685ad06 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -170,21 +170,28 @@ var CstyleBehaviour = function () { // Find what token we're inside. var tokens = session.getTokens(selection.start.row, selection.start.row)[0].tokens; var col = 0, token; - for (var x in tokens) { - token = tokens[x].type; - if ((tokens[x].value.length + col) > selection.start.column) { + var quotepos = -1; // Track whether we're inside an open quote. + + for (var x = 0; x < tokens.length; x++) { + token = tokens[x]; + if (token.type == "string") { + quotepos = -1; + } else if (quotepos < 0) { + quotepos = token.value.indexOf('"'); + } + if ((token.value.length + col) > selection.start.column) { break; } col += tokens[x].value.length; } // Try and be smart about when we auto insert. - if (token === "text" || !token || (token !== "comment" && selection.end.column === line.length)) { + if (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf('"') === token.value.length-1))) { return { text: '""', selection: [1,1] } - } else if (token === "string") { + } else if (token && token.type === "string") { // Ignore input and move right one if we're typing over the closing quote. var rightChar = line.substring(cursor.column, cursor.column + 1); if (rightChar == '"') { diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js new file mode 100644 index 00000000..7f1b02d9 --- /dev/null +++ b/lib/ace/mode/behaviour/xml.js @@ -0,0 +1,41 @@ +define(function(require, exports, module) { + +var oop = require("pilot/oop"); +var Behaviour = require('ace/mode/behaviour').Behaviour; +var CstyleBehaviour = require('ace/mode/behaviour/cstyle').CstyleBehaviour; + +var XmlBehaviour = function () { + + this.inherit(CstyleBehaviour, ["string_dquotes"]); // Get string behaviour + + this.add("brackets", "insertion", function (state, action, editor, session, text) { + if (text == '<') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "") { + return false; + } else { + return { + text: '<>', + selection: [1, 1] + } + } + } else if (text == '>') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '>') { // need some kind of matching check here + return { + text: '', + selection: [1, 1] + } + } + } + return false; + }); + +} +oop.inherits(XmlBehaviour, Behaviour); + +exports.XmlBehaviour = XmlBehaviour; +}); \ No newline at end of file diff --git a/lib/ace/mode/xml.js b/lib/ace/mode/xml.js index edaa5ffb..a6d5fa9c 100644 --- a/lib/ace/mode/xml.js +++ b/lib/ace/mode/xml.js @@ -41,9 +41,11 @@ var oop = require("pilot/oop"); var TextMode = require("ace/mode/text").Mode; var Tokenizer = require("ace/tokenizer").Tokenizer; var XmlHighlightRules = require("ace/mode/xml_highlight_rules").XmlHighlightRules; +var XmlBehaviour = require("ace/mode/behaviour/xml").XmlBehaviour; var Mode = function() { this.$tokenizer = new Tokenizer(new XmlHighlightRules().getRules()); + this.$behaviour = new XmlBehaviour(); }; oop.inherits(Mode, TextMode); From 0bad27ff92633c76b0bbe6c9e290dee17b6cb4a0 Mon Sep 17 00:00:00 2001 From: c-spencer Date: Wed, 25 May 2011 20:58:45 +0100 Subject: [PATCH 10/16] Update modes to use new embed syntax --- lib/ace/mode/behaviour/xml.js | 13 ++++++ lib/ace/mode/c_cpp_highlight_rules.js | 10 ++--- lib/ace/mode/csharp_highlight_rules.js | 11 +++-- lib/ace/mode/doc_comment_highlight_rules.js | 12 +++-- lib/ace/mode/html.js | 49 ++++++--------------- lib/ace/mode/html_highlight_rules.js | 16 +++---- lib/ace/mode/java_highlight_rules.js | 10 ++--- lib/ace/mode/javascript_highlight_rules.js | 10 ++--- lib/ace/mode/php_highlight_rules.js | 12 +++-- lib/ace/mode/svg.js | 41 ++++++----------- lib/ace/mode/svg_highlight_rules.js | 10 ++--- lib/ace/mode/text.js | 11 +++-- lib/ace/mode/text_highlight_rules.js | 17 ++++++- 13 files changed, 102 insertions(+), 120 deletions(-) diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js index 7f1b02d9..e4abfb7b 100644 --- a/lib/ace/mode/behaviour/xml.js +++ b/lib/ace/mode/behaviour/xml.js @@ -30,6 +30,19 @@ var XmlBehaviour = function () { selection: [1, 1] } } + } else if (text == "\n") { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChars = line.substring(cursor.column, cursor.column + 2); + if (rightChars == ')", next: "tag" @@ -184,15 +182,13 @@ var HtmlHighlightRules = function() { token: "text", regex: "<\\/(?=script)", next: "tag" - }); - - var cssRules = new CssHighlightRules().getRules(); - this.addRules(cssRules, "css-"); - this.$rules["css-start"].unshift({ + }], ["js-start"]); + + this.embedRules(CssHighlightRules, "css-", [{ token: "text", regex: "<\\/(?=style)", next: "tag" - }); + }], ["css-start"]); }; oop.inherits(HtmlHighlightRules, TextHighlightRules); diff --git a/lib/ace/mode/java_highlight_rules.js b/lib/ace/mode/java_highlight_rules.js index 6efcd07e..db7fe99b 100644 --- a/lib/ace/mode/java_highlight_rules.js +++ b/lib/ace/mode/java_highlight_rules.js @@ -7,8 +7,6 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR var JavaHighlightRules = function() { - var docComment = new DocCommentHighlightRules(); - // taken from http://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html var keywords = lang.arrayToMap( ("abstract|continue|for|new|switch|" + @@ -66,7 +64,7 @@ var JavaHighlightRules = function() { token : "comment", regex : "\\/\\/.*$" }, - docComment.getStartRule("doc-start"), + new DocCommentHighlightRules().getStartRule("doc-start"), { token : "comment", // multi line comment regex : "\\/\\*", @@ -156,9 +154,9 @@ var JavaHighlightRules = function() { } ] }; - - this.addRules(docComment.getRules(), "doc-"); - this.$rules["doc-start"][0].next = "start"; + + this.embedRules(DocCommentHighlightRules, "doc-", + [ new DocCommentHighlightRules().getEndRule("start") ]); }; oop.inherits(JavaHighlightRules, TextHighlightRules); diff --git a/lib/ace/mode/javascript_highlight_rules.js b/lib/ace/mode/javascript_highlight_rules.js index f5998deb..14b1795c 100644 --- a/lib/ace/mode/javascript_highlight_rules.js +++ b/lib/ace/mode/javascript_highlight_rules.js @@ -45,8 +45,6 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR var JavaScriptHighlightRules = function() { - var docComment = new DocCommentHighlightRules(); - var keywords = lang.arrayToMap( ("break|case|catch|continue|default|delete|do|else|finally|for|function|" + "if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|" + @@ -71,7 +69,7 @@ var JavaScriptHighlightRules = function() { token : "comment", regex : "\\/\\/.*$" }, - docComment.getStartRule("doc-start"), + new DocCommentHighlightRules().getStartRule("doc-start"), { token : "comment", // multi line comment regex : "\\/\\*", @@ -168,9 +166,9 @@ var JavaScriptHighlightRules = function() { } ] }; - - this.addRules(docComment.getRules(), "doc-"); - this.$rules["doc-start"][0].next = "start"; + + this.embedRules(DocCommentHighlightRules, "doc-", + [ new DocCommentHighlightRules().getEndRule("start") ]); }; oop.inherits(JavaScriptHighlightRules, TextHighlightRules); diff --git a/lib/ace/mode/php_highlight_rules.js b/lib/ace/mode/php_highlight_rules.js index 5e5d3922..a3c1e2dc 100644 --- a/lib/ace/mode/php_highlight_rules.js +++ b/lib/ace/mode/php_highlight_rules.js @@ -44,9 +44,7 @@ var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").D var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules; var PhpHighlightRules = function() { - - var docComment = new DocCommentHighlightRules(); - + var builtinFunctions = lang.arrayToMap( ('abs|acos|acosh|addcslashes|addslashes|aggregate|aggregate_info|aggregate_methods|' + 'aggregate_methods_by_list|aggregate_methods_by_regexp|aggregate_properties|aggregate_properties_by_list|' + @@ -476,7 +474,7 @@ var PhpHighlightRules = function() { token : "comment", regex : "#.*$" }, - docComment.getStartRule("doc-start"), + new DocCommentHighlightRules().getStartRule("doc-start"), { token : "comment", // multi line comment regex : "\\/\\*", @@ -596,9 +594,9 @@ var PhpHighlightRules = function() { } ] }; - - this.addRules(docComment.getRules(), "doc-"); - this.$rules["doc-start"][0].next = "start"; + + this.embedRules(DocCommentHighlightRules, "doc-", + [ new DocCommentHighlightRules().getEndRule("start") ]); }; oop.inherits(PhpHighlightRules, TextHighlightRules); diff --git a/lib/ace/mode/svg.js b/lib/ace/mode/svg.js index 4ba826a2..10384e57 100644 --- a/lib/ace/mode/svg.js +++ b/lib/ace/mode/svg.js @@ -42,10 +42,18 @@ var XmlMode = require("ace/mode/text").Mode; var JavaScriptMode = require("ace/mode/javascript").Mode; var Tokenizer = require("ace/tokenizer").Tokenizer; var SvgHighlightRules = require("ace/mode/svg_highlight_rules").SvgHighlightRules; +var XmlBehaviour = require("ace/mode/behaviour/xml").XmlBehaviour; var Mode = function() { - this.$tokenizer = new Tokenizer(new SvgHighlightRules().getRules()); - this.$js = new JavaScriptMode(); + this.highlighter = new SvgHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); + this.$behaviour = new XmlBehaviour(); + + + this.$embeds = highlighter.getEmbeds(); + this.createModeDelegates({ + "js-": JavaScriptMode + }); }; oop.inherits(Mode, XmlMode); @@ -53,38 +61,15 @@ oop.inherits(Mode, XmlMode); (function() { this.toggleCommentLines = function(state, doc, startRow, endRow) { - this.$delegate("toggleCommentLines", arguments, function() { - return 0; - }); + return 0; }; this.getNextLineIndent = function(state, line, tab) { - var self = this; - return this.$delegate("getNextLineIndent", arguments, function() { - return self.$getIndent(line); - }); + return self.$getIndent(line); }; this.checkOutdent = function(state, line, input) { - return this.$delegate("checkOutdent", arguments, function() { - return false; - }); - }; - - this.autoOutdent = function(state, doc, row) { - this.$delegate("autoOutdent", arguments); - }; - - this.$delegate = function(method, args, defaultHandler) { - var state = args[0]; - var split = state.split("js-"); - - if (!split[0] && split[1]) { - args[0] = split[1]; - return this.$js[method].apply(this.$js, args); - } - - return defaultHandler ? defaultHandler() : undefined; + return false; }; }).call(Mode.prototype); diff --git a/lib/ace/mode/svg_highlight_rules.js b/lib/ace/mode/svg_highlight_rules.js index 731e05a5..0f9ae5b9 100644 --- a/lib/ace/mode/svg_highlight_rules.js +++ b/lib/ace/mode/svg_highlight_rules.js @@ -65,11 +65,9 @@ var SvgHighlightRules = function() { }, { token : "string", regex : "'.*?'" - }]; - - var jsRules = new JavaScriptHighlightRules().getRules(); - this.addRules(jsRules, "js-"); - this.$rules["js-start"].unshift({ + }]; + + this.embedRules(JavaScriptHighlightRules, "js-", [{ token: "comment", regex: "\\/\\/.*(?=<\\/script>)", next: "tag" @@ -77,7 +75,7 @@ var SvgHighlightRules = function() { token: "text", regex: "<\\/(?=script)", next: "tag" - }); + }], ["js-start"]); }; diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index 7e2e96a2..b3eeac78 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -150,7 +150,9 @@ var Mode = function() { } this.$modes = {}; for (var i = 0; i < this.$embeds.length; i++) { - this.$modes[this.$embeds[i]] = new mapping[this.$embeds[i]](); + if (mapping[this.$embeds[i]]) { + this.$modes[this.$embeds[i]] = new mapping[this.$embeds[i]](); + } } var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformAction']; @@ -171,15 +173,16 @@ var Mode = function() { for (var i = 0; i < this.$embeds.length; i++) { var split = state.split(this.$embeds[i]); - + if (!this.$modes[this.$embeds[i]]) continue; + if (!split[0] && split[1]) { args[0] = split[1]; var mode = this.$modes[this.$embeds[i]]; return mode[method].apply(mode, args); } } - - return defaultHandler ? defaultHandler.apply(this, args) : undefined; + var ret = defaultHandler.apply(this, args); + return defaultHandler ? ret : undefined; }; this.transformAction = function(state, action, editor, session, param) { diff --git a/lib/ace/mode/text_highlight_rules.js b/lib/ace/mode/text_highlight_rules.js index 3ff947b1..317cb316 100644 --- a/lib/ace/mode/text_highlight_rules.js +++ b/lib/ace/mode/text_highlight_rules.js @@ -53,6 +53,19 @@ var TextHighlightRules = function() { }; }; +// Could probably do with improving and moving into lang. +var deepCopy = function (o) { + var clone = o.constructor(); + for (var k in o) { + if (typeof o[k] === "object") { + clone[k] = deepCopy(o[k]); + } else { + clone[k] = o[k]; + } + } + return clone; +}; + (function() { this.addRules = function(rules, prefix) { @@ -60,11 +73,13 @@ var TextHighlightRules = function() { var state = rules[key]; for (var i=0; i Date: Wed, 25 May 2011 21:17:53 +0100 Subject: [PATCH 11/16] Add license to xml behaviour --- lib/ace/mode/behaviour/xml.js | 38 +++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js index e4abfb7b..182b350e 100644 --- a/lib/ace/mode/behaviour/xml.js +++ b/lib/ace/mode/behaviour/xml.js @@ -1,3 +1,41 @@ +/* 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): + * Chris Spencer + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + define(function(require, exports, module) { var oop = require("pilot/oop"); From 58cf406fbd4c963f32a60cc4c930a45a0ca1e6a2 Mon Sep 17 00:00:00 2001 From: c-spencer Date: Wed, 25 May 2011 22:50:14 +0100 Subject: [PATCH 12/16] squash text highlighter console --- lib/ace/mode/text_highlight_rules.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ace/mode/text_highlight_rules.js b/lib/ace/mode/text_highlight_rules.js index 317cb316..ba8c8f4b 100644 --- a/lib/ace/mode/text_highlight_rules.js +++ b/lib/ace/mode/text_highlight_rules.js @@ -79,7 +79,6 @@ var deepCopy = function (o) { } else { rule.next = prefix + key; } - console.log(prefix, key, onext, rule.next); } this.$rules[prefix + key] = state; } From 97c4e880fee4fccb9ea3e741e3a64ae3a524529b Mon Sep 17 00:00:00 2001 From: c-spencer Date: Wed, 25 May 2011 23:14:17 +0100 Subject: [PATCH 13/16] Escape from all js/css embedded inside html --- lib/ace/mode/html_highlight_rules.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ace/mode/html_highlight_rules.js b/lib/ace/mode/html_highlight_rules.js index 752e1e9b..8a1f3e53 100644 --- a/lib/ace/mode/html_highlight_rules.js +++ b/lib/ace/mode/html_highlight_rules.js @@ -182,13 +182,13 @@ var HtmlHighlightRules = function() { token: "text", regex: "<\\/(?=script)", next: "tag" - }], ["js-start"]); + }]); this.embedRules(CssHighlightRules, "css-", [{ token: "text", regex: "<\\/(?=style)", next: "tag" - }], ["css-start"]); + }]); }; oop.inherits(HtmlHighlightRules, TextHighlightRules); From 5d1abb6bfc21ebb0fba2282d253827205e5dabeb Mon Sep 17 00:00:00 2001 From: c-spencer Date: Fri, 27 May 2011 10:29:11 +0100 Subject: [PATCH 14/16] Remove hasOwnProperty style iteration --- lib/ace/mode/behaviour.js | 8 ++------ lib/ace/mode/text.js | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/ace/mode/behaviour.js b/lib/ace/mode/behaviour.js index 6c145d22..c30afbad 100644 --- a/lib/ace/mode/behaviour.js +++ b/lib/ace/mode/behaviour.js @@ -56,12 +56,8 @@ var Behaviour = function() { this.addBehaviours = function (behaviours) { for (var key in behaviours) { - if (behaviours.hasOwnProperty(key)) { - for (var action in behaviours[key]) { - if (behaviours[key].hasOwnProperty(action)) { - this.add(key, action, behaviours[key][action]); - } - } + for (var action in behaviours[key]) { + this.add(key, action, behaviours[key][action]); } } } diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index b3eeac78..c457b5b5 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -189,7 +189,7 @@ var Mode = function() { if (this.$behaviour) { var behaviours = this.$behaviour.getBehaviours(); for (var key in behaviours) { - if (behaviours.hasOwnProperty(key) && behaviours[key][action]) { + if (behaviours[key][action]) { var ret = behaviours[key][action].apply(this, arguments); if (ret !== false) { return ret; From e153f53852154fabf986b2e41cb83a69ab015de8 Mon Sep 17 00:00:00 2001 From: c-spencer Date: Fri, 27 May 2011 10:48:28 +0100 Subject: [PATCH 15/16] Move deepCopy into pilot/lang --- lib/ace/mode/text_highlight_rules.js | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/lib/ace/mode/text_highlight_rules.js b/lib/ace/mode/text_highlight_rules.js index ba8c8f4b..654858b7 100644 --- a/lib/ace/mode/text_highlight_rules.js +++ b/lib/ace/mode/text_highlight_rules.js @@ -37,6 +37,8 @@ define(function(require, exports, module) { +var lang = require("pilot/lang"); + var TextHighlightRules = function() { // regexp must not have capturing parentheses @@ -53,19 +55,6 @@ var TextHighlightRules = function() { }; }; -// Could probably do with improving and moving into lang. -var deepCopy = function (o) { - var clone = o.constructor(); - for (var k in o) { - if (typeof o[k] === "object") { - clone[k] = deepCopy(o[k]); - } else { - clone[k] = o[k]; - } - } - return clone; -}; - (function() { this.addRules = function(rules, prefix) { @@ -103,7 +92,7 @@ var deepCopy = function (o) { this.addRules(embedRules, prefix); for (var i = 0; i < states.length; i++) { - Array.prototype.unshift.apply(this.$rules[states[i]], deepCopy(escapeRules)); + Array.prototype.unshift.apply(this.$rules[states[i]], lang.deepCopy(escapeRules)); } if (!this.$embeds) { From ba1d1927310d58d40274eb25b2ca99de3877626c Mon Sep 17 00:00:00 2001 From: c-spencer Date: Fri, 27 May 2011 13:51:40 +0100 Subject: [PATCH 16/16] Small tidy --- lib/ace/mode/text.js | 2 +- lib/ace/mode/text_highlight_rules.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index c457b5b5..40e4f506 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -172,9 +172,9 @@ var Mode = function() { var state = args[0]; for (var i = 0; i < this.$embeds.length; i++) { - var split = state.split(this.$embeds[i]); if (!this.$modes[this.$embeds[i]]) continue; + var split = state.split(this.$embeds[i]); if (!split[0] && split[1]) { args[0] = split[1]; var mode = this.$modes[this.$embeds[i]]; diff --git a/lib/ace/mode/text_highlight_rules.js b/lib/ace/mode/text_highlight_rules.js index 654858b7..e0feffa3 100644 --- a/lib/ace/mode/text_highlight_rules.js +++ b/lib/ace/mode/text_highlight_rules.js @@ -62,7 +62,6 @@ var TextHighlightRules = function() { var state = rules[key]; for (var i=0; i