From ba025f3e8726942b3b682f482071e1ac392b3287 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Tue, 20 Apr 2010 12:06:47 +0200 Subject: [PATCH] improve CSS and HTML auto indent --- src/mode/Css.js | 17 ++++++++++++++ src/mode/CssHighlightRules.js | 6 +++++ src/mode/Html.js | 11 ++++++++++ src/mode/JavaScript.js | 22 +++++++------------ src/mode/JavaScriptHighlightRules.js | 10 ++++----- src/mode/Text.js | 9 ++++++++ test/mode/CssTest.js | 33 ++++++++++++++++++++++++++++ test/mode/CssTokenizerTest.js | 9 ++++++++ test/mode/JavaScriptTokenizerTest.js | 11 ++++++++++ test/mode/TextTest.js | 23 +++++++++++++++++++ 10 files changed, 132 insertions(+), 19 deletions(-) create mode 100644 test/mode/CssTest.js create mode 100644 test/mode/TextTest.js diff --git a/src/mode/Css.js b/src/mode/Css.js index d4683c6b..b8c06461 100644 --- a/src/mode/Css.js +++ b/src/mode/Css.js @@ -4,3 +4,20 @@ ace.mode.Css = function() { this.$tokenizer = new ace.Tokenizer(new ace.mode.CssHighlightRules().getRules()); }; ace.inherits(ace.mode.Css, ace.mode.Text); + +ace.mode.Css.prototype.getNextLineIndent = function(line, state, tab) { + var indent = this.$getIndent(line); + + // ignore braces in comments + var tokens = this.$tokenizer.getLineTokens(line, state).tokens; + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + var match = line.match(/^.*\{\s*$/); + if (match) { + indent += tab; + } + + return indent; +}; \ No newline at end of file diff --git a/src/mode/CssHighlightRules.js b/src/mode/CssHighlightRules.js index 2044974f..35376d1e 100644 --- a/src/mode/CssHighlightRules.js +++ b/src/mode/CssHighlightRules.js @@ -141,6 +141,12 @@ ace.mode.CssHighlightRules = function() { }, { token : "number", // hex3 color regex : "#[a-fA-F0-9]{3}" + }, { + token : "lparen", + regex : "\{" + }, { + token : "rparen", + regex : "\}" }, { token : function(value) { if (properties[value.toLowerCase()]) { diff --git a/src/mode/Html.js b/src/mode/Html.js index 036e0656..631aa038 100644 --- a/src/mode/Html.js +++ b/src/mode/Html.js @@ -4,6 +4,7 @@ ace.mode.Html = function() { this.$tokenizer = new ace.Tokenizer(new ace.mode.HtmlHighlightRules().getRules()); this._js = new ace.mode.JavaScript(); + this._css = new ace.mode.Css(); }; ace.inherits(ace.mode.Html, ace.mode.Text); @@ -13,6 +14,11 @@ ace.mode.Html.prototype.toggleCommentLines = function(doc, range, state) { return this._js.toggleCommentLines(doc, range, state); } + var split = state.split("css-"); + if (!split[0] && split[1]) { + return this._css.toggleCommentLines(doc, range, state); + } + return 0; }; @@ -22,5 +28,10 @@ ace.mode.Html.prototype.getNextLineIndent = function(line, state, tab) { return this._js.getNextLineIndent(line, split[1], tab); } + var split = state.split("css-"); + if (!split[0] && split[1]) { + return this._css.getNextLineIndent(line, split[1], tab); + } + return ""; }; \ No newline at end of file diff --git a/src/mode/JavaScript.js b/src/mode/JavaScript.js index 71c1a2f6..017570aa 100644 --- a/src/mode/JavaScript.js +++ b/src/mode/JavaScript.js @@ -14,28 +14,22 @@ ace.mode.JavaScript.prototype.toggleCommentLines = function(doc, range, state) { }; ace.mode.JavaScript.prototype.getNextLineIndent = function(line, state, tab) { + var indent = this.$getIndent(line); + if (state == "start") { - var re = /^(\s*).*[\{\(\[]\s*$/; - var match = line.match(re); + var match = line.match(/^.*[\{\(\[]\s*$/); if (match) { - return (match[1] || "") + tab; + indent += tab; } } else if (state == "doc-comment") { - var re = /^(\s*)(\/?)\*.*$/; - var match = line.match(re); + var match = line.match(/^\s*(\/?)\*/); if (match) { - var indent = match[1]; - if (match[2]) { + if (match[1]) { indent += " "; } - return indent + "* "; + indent += "* "; } } - var match = line.match(/^(\s+).*$/); - if (match) { - return match[1]; - } - - return ""; + return indent; }; \ No newline at end of file diff --git a/src/mode/JavaScriptHighlightRules.js b/src/mode/JavaScriptHighlightRules.js index 661dd168..61819ac1 100644 --- a/src/mode/JavaScriptHighlightRules.js +++ b/src/mode/JavaScriptHighlightRules.js @@ -74,11 +74,11 @@ ace.mode.JavaScriptHighlightRules = function() { }, regex : "[a-zA-Z_][a-zA-Z0-9_]*\\b" }, { - token : function(value) { - // return parens[value]; - return "text"; - }, - regex : "[\\[\\]\\(\\)\\{\\}]" + token : "lparen", + regex : "[\\[\\(\\{]" + }, { + token : "rparen", + regex : "[\\]\\)\\}]" }, { token : "text", regex : "\\s+" diff --git a/src/mode/Text.js b/src/mode/Text.js index 99d0f537..5baf0de8 100644 --- a/src/mode/Text.js +++ b/src/mode/Text.js @@ -19,5 +19,14 @@ ace.mode.Text.prototype.toggleCommentLines = function(doc, range, state) { }; ace.mode.Text.prototype.getNextLineIndent = function(line, state, tab) { + return ""; +}; + +ace.mode.Text.prototype.$getIndent = function(line) { + var match = line.match(/^(\s+)/); + if (match) { + return match[1]; + } + return ""; }; \ No newline at end of file diff --git a/test/mode/CssTest.js b/test/mode/CssTest.js new file mode 100644 index 00000000..c7abdc0c --- /dev/null +++ b/test/mode/CssTest.js @@ -0,0 +1,33 @@ +var CssTest = new TestCase("mode.CssTest", { + + setUp : function() { + this.mode = new ace.mode.Css(); + }, + + "test: toggle comment lines should not do anything" : function() { + var doc = new ace.TextDocument([" abc", "cde", "fg"].join("\n")); + + var range = { + start: {row: 0, column: 3}, + end: {row: 1, column: 1} + }; + + var comment = this.mode.toggleCommentLines(doc, range, "start"); + assertEquals([" abc", "cde", "fg"].join("\n"), doc.toString()); + }, + + + "test: lines should keep indentation" : function() { + assertEquals(" ", this.mode.getNextLineIndent(" abc", "start", " ")); + assertEquals("\t", this.mode.getNextLineIndent("\tabc", "start", " ")); + }, + + "test: new line after { should increase indent" : function() { + assertEquals(" ", this.mode.getNextLineIndent(" abc{", "start", " ")); + assertEquals("\t ", this.mode.getNextLineIndent("\tabc { ", "start", " ")); + }, + + "test: no indent increase after { in a comment" : function() { + assertEquals(" ", this.mode.getNextLineIndent(" /*{", "start", " ")); + } +}); \ No newline at end of file diff --git a/test/mode/CssTokenizerTest.js b/test/mode/CssTokenizerTest.js index 3d84af00..56d1ce0f 100644 --- a/test/mode/CssTokenizerTest.js +++ b/test/mode/CssTokenizerTest.js @@ -24,5 +24,14 @@ var CssTest = new TestCase("mode.CssTest", { assertEquals(1, tokens.length); assertEquals("number", tokens[0].type); + }, + + "test: tokenize parens" : function() { + var tokens = this.tokenizer.getLineTokens("{()}", "start").tokens; + + assertEquals(3, tokens.length); + assertEquals("lparen", tokens[0].type); + assertEquals("text", tokens[1].type); + assertEquals("rparen", tokens[2].type); } }); \ No newline at end of file diff --git a/test/mode/JavaScriptTokenizerTest.js b/test/mode/JavaScriptTokenizerTest.js index 9c0cd8b3..60f628e4 100644 --- a/test/mode/JavaScriptTokenizerTest.js +++ b/test/mode/JavaScriptTokenizerTest.js @@ -37,5 +37,16 @@ var JavaScriptTokenizerTest = new TestCase("mode.JavaScriptTokenizerTest", { assertEquals("doc-comment", tokens[0].type); assertEquals("doc-comment-tag", tokens[1].type); assertEquals("doc-comment", tokens[2].type); + }, + + "test: tokenize parens" : function() { + var line = "[{( )}]"; + + var tokens = this.tokenizer.getLineTokens(line, "start").tokens; + + assertEquals(3, tokens.length); + assertEquals("lparen", tokens[0].type); + assertEquals("text", tokens[1].type); + assertEquals("rparen", tokens[2].type); } }); \ No newline at end of file diff --git a/test/mode/TextTest.js b/test/mode/TextTest.js new file mode 100644 index 00000000..63418d7e --- /dev/null +++ b/test/mode/TextTest.js @@ -0,0 +1,23 @@ +var TextTest = new TestCase("mode.TextTest", { + + setUp : function() { + this.mode = new ace.mode.Text(); + }, + + "test: toggle comment lines should not do anything" : function() { + var doc = new ace.TextDocument([" abc", "cde", "fg"].join("\n")); + + var range = { + start: {row: 0, column: 3}, + end: {row: 1, column: 1} + }; + + var comment = this.mode.toggleCommentLines(doc, range, "start"); + assertEquals([" abc", "cde", "fg"].join("\n"), doc.toString()); + }, + + + "text: lines should not be indented" : function() { + assertEquals("", this.mode.getNextLineIndent(" abc", " ")); + } +}); \ No newline at end of file