diff --git a/lib/ace/mode/_test/text_php.txt b/lib/ace/mode/_test/text_php.txt
new file mode 100644
index 00000000..b76aa8a5
--- /dev/null
+++ b/lib/ace/mode/_test/text_php.txt
@@ -0,0 +1,24 @@
+ not &js;
diff --git a/lib/ace/mode/_test/tokens_gitignore.json b/lib/ace/mode/_test/tokens_gitignore.json
new file mode 100644
index 00000000..8689a724
--- /dev/null
+++ b/lib/ace/mode/_test/tokens_gitignore.json
@@ -0,0 +1,33 @@
+[[
+ "start",
+ ["comment","# A sample .gitignore file."]
+],[
+ "start"
+],[
+ "start",
+ ["text",".buildlog"]
+],[
+ "start",
+ ["text",".DS_Store"]
+],[
+ "start",
+ ["text",".svn"]
+],[
+ "start"
+],[
+ "start",
+ ["comment","# Negated patterns:"]
+],[
+ "start",
+ ["keyword","!foo.bar"]
+],[
+ "start"
+],[
+ "start",
+ ["comment","# Also ignore user settings..."]
+],[
+ "start",
+ ["text","/.settings"]
+],[
+ "start"
+]]
\ No newline at end of file
diff --git a/lib/ace/mode/_test/tokens_lsl.json b/lib/ace/mode/_test/tokens_lsl.json
index 93575a2c..2248a607 100644
--- a/lib/ace/mode/_test/tokens_lsl.json
+++ b/lib/ace/mode/_test/tokens_lsl.json
@@ -500,4 +500,4 @@
["paren.rparen.lsl","}"]
],[
"start"
-]]
+]]
\ No newline at end of file
diff --git a/lib/ace/mode/_test/tokens_lua.json b/lib/ace/mode/_test/tokens_lua.json
index 3fde966d..b60c7cb1 100644
--- a/lib/ace/mode/_test/tokens_lua.json
+++ b/lib/ace/mode/_test/tokens_lua.json
@@ -345,4 +345,4 @@
["text"," "],
["comment","--[[ blah ]]"],
["paren.rparen",")"]
-]]
+]]
\ No newline at end of file
diff --git a/lib/ace/mode/_test/tokens_php.json b/lib/ace/mode/_test/tokens_php.json
index d8a41eec..d1458a65 100644
--- a/lib/ace/mode/_test/tokens_php.json
+++ b/lib/ace/mode/_test/tokens_php.json
@@ -129,6 +129,43 @@
],[
"php-start"
],[
- "start",
+ ["php-start","js-start"],
+ ["support.php_tag","?>"],
+ ["text.xml"," "],
+ ["meta.tag.punctuation.tag-open.xml","<"],
+ ["meta.tag.script.tag-name.xml","script"],
+ ["meta.tag.punctuation.tag-close.xml",">"],
+ ["text"," "],
+ ["support.php_tag",""]
+],[
+ "js-comment_regex_allowed",
+ ["comment","/*this is js "],
+ ["support.php_tag",""]
+],[
+ "start",
+ ["meta.tag.punctuation.end-tag-open.xml",""],
+ ["meta.tag.script.tag-name.xml","script"],
+ ["meta.tag.punctuation.tag-close.xml",">"],
+ ["text.xml"," not "],
+ ["constant.language.escape.reference.xml","&js;"]
+],[
+ "start"
]]
\ No newline at end of file
diff --git a/lib/ace/mode/_test/tokens_vala.json b/lib/ace/mode/_test/tokens_vala.json
new file mode 100644
index 00000000..efe6e7c8
--- /dev/null
+++ b/lib/ace/mode/_test/tokens_vala.json
@@ -0,0 +1,158 @@
+[[
+ "start",
+ ["meta.using.vala",""],
+ ["keyword.other.using.vala","using"],
+ ["meta.using.vala"," "],
+ ["storage.modifier.using.vala","Gtk"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "start",
+ ["text"," "]
+],[
+ "text0",
+ ["storage.type.primitive.array.vala","int"],
+ ["text"," main ("],
+ ["storage.type.primitive.array.vala","string"],
+ ["text","[] args) {"]
+],[
+ "text0",
+ ["text"," "],
+ ["storage.type.vala","Gtk"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","init ("],
+ ["storage.modifier.vala","ref"],
+ ["text"," args)"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," "],
+ ["storage.type.primitive.vala","var"],
+ ["text"," foo "],
+ ["keyword.operator.assignment.vala","="],
+ ["text"," "],
+ ["keyword.control.new.vala","new"],
+ ["text"," "],
+ ["storage.type.generic.vala","MyFoo>"],
+ ["text","()"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0"
+],[
+ "text0",
+ ["text"," "],
+ ["storage.type.primitive.vala","var"],
+ ["text"," window "],
+ ["keyword.operator.assignment.vala","="],
+ ["text"," "],
+ ["keyword.control.new.vala","new"],
+ ["text"," "],
+ ["storage.type.vala","Window"],
+ ["text","()"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," window"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","title "],
+ ["keyword.operator.assignment.vala","="],
+ ["text"," "],
+ ["punctuation.definition.string.begin.vala","\""],
+ ["string.quoted.double.vala","Hello, World!"],
+ ["punctuation.definition.string.end.vala","\""],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," window"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","border_width "],
+ ["keyword.operator.assignment.vala","="],
+ ["text"," "],
+ ["constant.numeric.vala","10"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," window"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","window_position "],
+ ["keyword.operator.assignment.vala","="],
+ ["text"," "],
+ ["storage.type.vala","WindowPosition"],
+ ["keyword.operator.dereference.vala","."],
+ ["constant.other.vala","CENTER"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," window"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","set_default_size("],
+ ["constant.numeric.vala","350"],
+ ["text",", "],
+ ["constant.numeric.vala","70"],
+ ["text",")"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," window"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","destroy"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","connect("],
+ ["storage.type.vala","Gtk"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","main_quit)"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," "]
+],[
+ "text0",
+ ["text"," "],
+ ["storage.type.primitive.vala","var"],
+ ["text"," label "],
+ ["keyword.operator.assignment.vala","="],
+ ["text"," "],
+ ["keyword.control.new.vala","new"],
+ ["text"," "],
+ ["storage.type.vala","Label"],
+ ["text","("],
+ ["punctuation.definition.string.begin.vala","\""],
+ ["string.quoted.double.vala","Hello, World!"],
+ ["punctuation.definition.string.end.vala","\""],
+ ["text",")"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," "]
+],[
+ "text0",
+ ["text"," window"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","add(label)"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," window"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","show_all()"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," "]
+],[
+ "text0",
+ ["text"," "],
+ ["storage.type.vala","Gtk"],
+ ["keyword.operator.dereference.vala","."],
+ ["text","main()"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "text0",
+ ["text"," "],
+ ["keyword.control.vala","return"],
+ ["text"," "],
+ ["constant.numeric.vala","0"],
+ ["punctuation.terminator.vala",";"]
+],[
+ "start",
+ ["text","}"]
+]]
\ No newline at end of file
diff --git a/lib/ace/mode/_test/tokens_xquery.json b/lib/ace/mode/_test/tokens_xquery.json
deleted file mode 100644
index aaf9ab9b..00000000
--- a/lib/ace/mode/_test/tokens_xquery.json
+++ /dev/null
@@ -1,44 +0,0 @@
-[[
- "[\"start\"]",
- ["keyword","xquery"],
- ["text"," "],
- ["keyword","version"],
- ["text"," "],
- ["string","\""],
- ["string","1.0"],
- ["string","\""],
- ["text",";"]
-],[
- "[\"start\"]"
-],[
- "[\"start\"]",
- ["keyword","let"],
- ["text"," "],
- ["variable","$message"],
- ["text"," "],
- ["keyword.operator",":="],
- ["text"," "],
- ["string","\""],
- ["string","Hello World!"],
- ["string","\""]
-],[
- "[\"start\",\"StartTag\",\"TagContent\"]",
- ["keyword","return"],
- ["text"," "],
- ["meta.tag",""]
-],[
- "[\"start\",\"StartTag\",\"TagContent\"]",
- ["text"," "],
- ["meta.tag",""],
- ["text","{"],
- ["variable","$message"],
- ["text","}"],
- ["meta.tag",""]
-],[
- "[\"start\"]",
- ["meta.tag",""]
-],[
- "[\"start\"]"
-]]
\ No newline at end of file
diff --git a/lib/ace/mode/sh_highlight_rules.js b/lib/ace/mode/sh_highlight_rules.js
index 73ece2f8..43f536f4 100644
--- a/lib/ace/mode/sh_highlight_rules.js
+++ b/lib/ace/mode/sh_highlight_rules.js
@@ -99,6 +99,62 @@ var ShHighlightRules = function() {
}, {
defaultToken: "string"
}]
+ }, {
+ stateName: "heredoc",
+ onMatch : function(value, currentState, stack) {
+ var next = value[2] == '-' ? "indentedHeredoc" : "heredoc";
+ var tokens = value.split(this.splitRegex);
+ stack.push(next, tokens[4]);
+ return [
+ {type:"constant", value: tokens[1]},
+ {type:"text", value: tokens[2]},
+ {type:"string", value: tokens[3]},
+ {type:"support.class", value: tokens[4]},
+ {type:"string", value: tokens[5]}
+ ];
+ },
+ regex : "(<<-?)(\\s*)(['\"`]?)([\\w\-]+)(['\"`]?)",
+ rules: {
+ heredoc: [{
+ onMatch: function(value, currentState, stack) {
+ if (value === stack[1]) {
+ stack.shift();
+ stack.shift();
+ this.next = stack[0] || "start";
+ return "support.class";
+ }
+ this.next = "";
+ return "string";
+ },
+ regex: ".*$",
+ next: "start"
+ }],
+ indentedHeredoc: [{
+ token: "string",
+ regex: "^ +"
+ }, {
+ onMatch: function(value, currentState, stack) {
+ if (value === stack[1]) {
+ stack.shift();
+ stack.shift();
+ this.next = stack[0] || "start";
+ return "support.class";
+ }
+ this.next = "";
+ return "string";
+ },
+ regex: ".*$",
+ next: "start"
+ }]
+ }
+ }, {
+ regex : "$",
+ token : "empty",
+ next : function(currentState, stack) {
+ if (stack[0] === "heredoc" || stack[0] === "indentedHeredoc")
+ return stack[0];
+ return currentState;
+ }
}, {
token : "variable.language",
regex : builtinVariable
diff --git a/lib/ace/tokenizer.js b/lib/ace/tokenizer.js
index 64bf59e8..85fa6c7b 100644
--- a/lib/ace/tokenizer.js
+++ b/lib/ace/tokenizer.js
@@ -268,11 +268,14 @@ var Tokenizer = function(rules) {
type = rule.token;
if (rule.next) {
- if (typeof rule.next == "string")
+ if (typeof rule.next == "string") {
+ if (stack.length && stack[0] == currentState && stack[1] == rule.next)
+ stack.shift();
currentState = rule.next;
- else
+ } else {
currentState = rule.next(currentState, stack);
-
+ }
+
state = this.states[currentState];
if (!state) {
window.console && console.error && console.error(currentState, "doesn't exist");