From ed223cb7fdf7c7baa323013a0ac68e6d77faa153 Mon Sep 17 00:00:00 2001 From: DanyaPostfactum Date: Mon, 24 Jun 2013 18:55:07 +1000 Subject: [PATCH] Rewrite xml rules. --- lib/ace/mode/behaviour/xml.js | 18 ++- lib/ace/mode/folding/xml.js | 6 +- lib/ace/mode/xml_highlight_rules.js | 179 +++++++++++++++++++++++++--- 3 files changed, 173 insertions(+), 30 deletions(-) diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js index 0d03b763..1ee39f39 100644 --- a/lib/ace/mode/behaviour/xml.js +++ b/lib/ace/mode/behaviour/xml.js @@ -37,14 +37,9 @@ var CstyleBehaviour = require("./cstyle").CstyleBehaviour; var TokenIterator = require("../../token_iterator").TokenIterator; function hasType(token, type) { - var hasType = true; - var typeList = token.type.split('.'); - var needleList = type.split('.'); - needleList.forEach(function(needle){ - if (typeList.indexOf(needle) == -1) { - hasType = false; - return false; - } + var tokenTypes = token.type.split('.'); + return type.split('.').every(function(type){ + return (tokenTypes.indexOf(type) !== -1); }); return hasType; } @@ -58,6 +53,9 @@ var XmlBehaviour = function () { var position = editor.getCursorPosition(); var iterator = new TokenIterator(session, position.row, position.column); var token = iterator.getCurrentToken(); + + if (token && hasType(token, 'string') && iterator.getCurrentTokenColumn() + token.value.length > position.column) + return; var atCursor = false; if (!token || !hasType(token, 'meta.tag') && !(hasType(token, 'text') && token.value.match('/'))){ do { @@ -66,8 +64,8 @@ var XmlBehaviour = function () { } else { atCursor = true; } - if (!token || !hasType(token, 'meta.tag-name') || iterator.stepBackward().value.match('/')) { - return + if (!token || !hasType(token, 'meta.tag.name') || iterator.stepBackward().value.match('/')) { + return; } var tag = token.value; if (atCursor){ diff --git a/lib/ace/mode/folding/xml.js b/lib/ace/mode/folding/xml.js index 63842e93..61d103f1 100644 --- a/lib/ace/mode/folding/xml.js +++ b/lib/ace/mode/folding/xml.js @@ -68,7 +68,7 @@ oop.inherits(FoldMode, BaseFoldMode); var value = ""; for (var i = 0; i < tokens.length; i++) { var token = tokens[i]; - if (token.type.indexOf("meta.tag") === 0) + if (token.type.indexOf("meta.tag") !== -1) value += token.value; else value += lang.stringRepeat(" ", token.value.length); @@ -105,7 +105,7 @@ oop.inherits(FoldMode, BaseFoldMode); var start; do { - if (token.type.indexOf("meta.tag") === 0) { + if (token.type.indexOf("meta.tag") !== -1) { if (!start) { var start = { row: iterator.getCurrentTokenRow(), @@ -138,7 +138,7 @@ oop.inherits(FoldMode, BaseFoldMode); var end; do { - if (token.type.indexOf("meta.tag") === 0) { + if (token.type.indexOf("meta.tag") !== -1) { if (!end) { end = { row: iterator.getCurrentTokenRow(), diff --git a/lib/ace/mode/xml_highlight_rules.js b/lib/ace/mode/xml_highlight_rules.js index 02003b3d..0589ee52 100644 --- a/lib/ace/mode/xml_highlight_rules.js +++ b/lib/ace/mode/xml_highlight_rules.js @@ -35,36 +35,181 @@ var oop = require("../lib/oop"); var xmlUtil = require("./xml_util"); var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; -var XmlHighlightRules = function() { +var XmlHighlightRules = function(normalize) { this.$rules = { start : [ - {token : "text", regex : "<\\!\\[CDATA\\[", next : "cdata"}, - {token : "xml-pe", regex : "<\\?.*?\\?>"}, - {token : "comment", regex : "<\\!--", next : "comment"}, - {token : "xml-pe", regex : "<\\!.*?>"}, - {token : "meta.tag", regex : "<\\/?", next : "tag"}, - {token : "text", regex : "\\s+"}, + {token : "punctuation.string.begin", regex : "<\\!\\[CDATA\\[", next : "cdata"}, { - token : "constant.character.entity", - regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)" - } + token : ["punctuation.instruction.begin", "keyword.instruction"], + regex : "(<\\?)(xml)(?=[\\s])", next : "xml_declaration" + }, + { + token : ["punctuation.instruction.begin", "keyword.instruction"], + regex : "(<\\?)([-_a-zA-Z0-9]+)", next : "instruction" + }, + {token : "comment", regex : "<\\!--", next : "comment"}, + { + token : ["punctuation.doctype.begin", "keyword.doctype"], + regex : "(<\\!)(DOCTYPE)(?=[\\s])", next : "doctype" + }, + {include : "tag"}, + {include : "reference"} ], - + + xml_declaration : [ + {include : "attributes"}, + {include : "instruction"} + ], + + instruction : [ + {token : "punctuation.instruction.end", regex : "\\?>", next : "start"} + ], + + doctype : [ + {include : "space"}, + {include : "string"}, + {token : "punctuation.doctype.end", regex : ">", next : "start"}, + {token : "text", regex : "[-_a-zA-Z0-9:]+"}, + {token : "punctuation.begin", regex : "\\[", push : "declarations"} + ], + + declarations : [{ + token : "text", + regex : "\\s+" + }, { + token: "punctuation.end", + regex: "]", + next: "pop" + }, { + token : ["punctuation.begin", "keyword"], + regex : "(<\\!)([-_a-zA-Z0-9]+)", + push : [{ + token : "text", + regex : "\\s+" + }, + { + token : "punctuation.end", + regex : ">", + next : "pop" + }, + {include : "string"}] + }], + cdata : [ - {token : "text", regex : "\\]\\]>", next : "start"}, + {token : "string.end", regex : "\\]\\]>", next : "start"}, {token : "text", regex : "\\s+"}, {token : "text", regex : "(?:[^\\]]|\\](?!\\]>))+"} ], comment : [ - {token : "comment", regex : ".*?-->", next : "start"}, - {token : "comment", regex : ".+"} - ] + {token : "comment", regex : "-->", next : "start"}, + {defaultToken : "comment"} + ], + + tag : [{ + token : ["punctuation.meta.tag.begin", "meta.tag.name"], + regex : "(<)((?:[-_a-zA-Z0-9]+:)?[-_a-zA-Z0-9]+)", + next: [ + {include : "attributes"}, + {token : "punctuation.meta.tag.end", regex : "/?>", next : "start"} + ] + }, { + token : ["punctuation.meta.tag.begin", "meta.tag.name"], + regex : "(", next : "start"} + ] + }], + + space : [ + {token : "text", regex : "\\s+"} + ], + + reference : [{ + token : "constant.language.escape", + regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)" + }, { + token : "invalid.illegal", regex : "&" + }], + + string: [{ + token : "string", + regex : "'", + push : "string_inner" + }, { + token : "string", + regex : '"', + push : "qqstring_inner" + }], + + qstring_inner: [ + {token : "string", regex: "'", next: "pop"}, + {include : "reference"}, + {defaultToken : "string"} + ], + + qqstring_inner: [ + {token : "string", regex: '"', next: "pop"}, + {include : "reference"}, + {defaultToken : "string"} + ], + + attributes: [{ + token : "entity.other.attribute-name", + regex : "(?:[-_a-zA-Z0-9]+:)?[-_a-zA-Z0-9]+" + }, { + token : "keyword.operator.separator", + regex : "=" + }, { + include : "space" + }, { + include : "string" + }] }; - - xmlUtil.tag(this.$rules, "tag", "start"); + + if (this.constructor === XmlHighlightRules) + this.normalizeRules(); }; + +(function() { + + this.embedTagRules = function(HighlightRules, prefix, tag){ + this.$rules.tag.unshift({ + token : ["punctuation.meta.tag.begin." + tag, "meta.tag.name." + tag], + regex : "(<)(" + tag + ")", + next: [ + {include : "space"}, + {include : "attributes"}, + {token : "punctuation.meta.tag.end." + tag, regex : "/?>", next : prefix + "start"} + ] + }); + + this.$rules[tag + "-end"] = [ + {include : "space"}, + {token : "punctuation.meta.tag.end." + tag, regex : ">", next: "start", + onMatch : function(value, currentState, stack) { + stack.splice(0); + return this.token; + }} + ] + + this.embedRules(HighlightRules, prefix, [{ + token: ["punctuation.meta.tag.begin." + tag, "meta.tag.name." + tag], + regex : "(" + }]); + }; + +}).call(TextHighlightRules.prototype); + oop.inherits(XmlHighlightRules, TextHighlightRules); exports.XmlHighlightRules = XmlHighlightRules;