diff --git a/ChangeLog.txt b/ChangeLog.txt index 7c3db96d..86399b5e 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,8 +1,15 @@ - + + * API Changes - `editor.commands.commandKeyBinding` now contains direct map from keys to commands instead of grouping them by hashid - - +* New Features + - Improved autoindent for html and php modes (Adam Jimenez) + - Find All from searchbox (Colton Voege) + +* new language modes + - Elixir, Elm + 2014.09.21 Version 1.1.7 * Bugfixes diff --git a/demo/kitchen-sink/docs/elixir.ex b/demo/kitchen-sink/docs/elixir.ex new file mode 100644 index 00000000..bb6a45f1 --- /dev/null +++ b/demo/kitchen-sink/docs/elixir.ex @@ -0,0 +1,42 @@ +defmodule HelloModule do + @moduledoc """ + This is supposed to be `markdown`. + __Yes__ this is [mark](http://down.format) + + # Truly + + ## marked + + * with lists + * more + * and more + + Even.with(code) + blocks |> with |> samples + + _Docs are first class citizens in Elixir_ (Jose Valim) + """ + + # A "Hello world" function + def some_fun do + IO.puts "Juhu Kinners!" + end + # A private function + defp priv do + is_regex ~r""" + This is a regex + spanning several + lines. + """ + x = elem({ :a, :b, :c }, 0) #=> :a + end +end + +test_fun = fn(x) -> + cond do + x > 10 -> + :greater_than_ten + true -> + :maybe_ten + end +end \ No newline at end of file diff --git a/lib/ace/ext/language_tools.js b/lib/ace/ext/language_tools.js index 4687efd5..12fcf5b2 100644 --- a/lib/ace/ext/language_tools.js +++ b/lib/ace/ext/language_tools.js @@ -40,6 +40,9 @@ var util = require("../autocomplete/util"); var textCompleter = require("../autocomplete/text_completer"); var keyWordCompleter = { getCompletions: function(editor, session, pos, prefix, callback) { + if (session.$mode.completer) { + return session.$mode.completer.getCompletions(editor, session, pos, prefix, callback); + } var state = editor.session.getState(pos.row); var completions = session.$mode.getCompletions(state, session, pos, prefix); callback(null, completions); diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 3f85c5b3..9e012f51 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -69,6 +69,7 @@ var supportedModes = { DummySyntax: ["dummy"], Eiffel: ["e"], EJS: ["ejs"], + Elixir: ["ex|exs"], Elm: ["elm"], Erlang: ["erl|hrl"], Forth: ["frt|fs|ldr"], diff --git a/lib/ace/mode/_test/highlight_rules_test.js b/lib/ace/mode/_test/highlight_rules_test.js index 647ca3c3..c3b877ec 100644 --- a/lib/ace/mode/_test/highlight_rules_test.js +++ b/lib/ace/mode/_test/highlight_rules_test.js @@ -58,12 +58,13 @@ function checkModes() { } function generateTestData() { - var docs = jsFileList(cwd + root); + var docRoot = root + "/demo/kitchen-sink/docs"; + var docs = fs.readdirSync(docRoot); var specialDocs = fs.readdirSync(cwd); var modes = modeList(); - console.log("Docs:", docs); - console.log("Modes:", modes); + // console.log("Docs:", docs); + // console.log("Modes:", modes); docs.forEach(function(docName) { var p = docName.toLowerCase().split("."); @@ -79,16 +80,19 @@ function generateTestData() { var filePath = "text_" + modeName + ".txt"; if (specialDocs.indexOf(filePath) == -1) { - filePath = root + "/" + docName; + filePath = docRoot + "/" + docName; + } else { + filePath = cwd + filePath; } - var text = fs.readFileSync(cwd + filePath, "utf8"); + var text = fs.readFileSync(filePath, "utf8"); try { var Mode = require("../" + modeName).Mode; } catch(e) { console.warn("Can't load mode :" + modeName, p, e); return; } + console.log(modeName); var tokenizer = new Mode().getTokenizer(); var state = "start"; diff --git a/lib/ace/mode/_test/tokens_eiffel.json b/lib/ace/mode/_test/tokens_eiffel.json new file mode 100644 index 00000000..344dbc62 --- /dev/null +++ b/lib/ace/mode/_test/tokens_eiffel.json @@ -0,0 +1,141 @@ +[[ + "start", + ["keyword","note"] +],[ + "start", + ["text","\t"], + ["identifier","description"], + ["keyword.operator",":"], + ["text"," "], + ["string.quoted.double","\"Represents a person.\""] +],[ + "start" +],[ + "start", + ["keyword","class"] +],[ + "start", + ["text","\t"], + ["entity.name.type","PERSON"] +],[ + "start" +],[ + "start", + ["keyword","create"] +],[ + "start", + ["text","\t"], + ["identifier","make"], + ["keyword.operator",","], + ["text"," "], + ["identifier","make_unknown"] +],[ + "start" +],[ + "start", + ["keyword","feature"], + ["text"," "], + ["paren.lparen","{"], + ["entity.name.type","NONE"], + ["paren.rparen","}"], + ["text"," "], + ["comment.line.double-dash","-- Creation"] +],[ + "start" +],[ + "start", + ["text","\t"], + ["identifier","make"], + ["text"," "], + ["paren.lparen","("], + ["identifier","a_name"], + ["keyword.operator",":"], + ["text"," "], + ["keyword","like"], + ["text"," "], + ["identifier","name"], + ["paren.rparen",")"] +],[ + "start", + ["text","\t\t\t"], + ["comment.line.double-dash","-- Create a person with `a_name' as `name'."] +],[ + "start", + ["text","\t\t"], + ["keyword","do"] +],[ + "start", + ["text","\t\t\t"], + ["identifier","name"], + ["text"," "], + ["keyword.operator",":="], + ["text"," "], + ["identifier","a_name"] +],[ + "start", + ["text","\t\t"], + ["keyword","ensure"] +],[ + "start", + ["text","\t\t\t"], + ["identifier","name"], + ["text"," "], + ["keyword.operator","="], + ["text"," "], + ["identifier","a_name"] +],[ + "start", + ["text","\t\t"], + ["keyword","end"] +],[ + "start" +],[ + "start", + ["text","\t"], + ["identifier","make_unknown"] +],[ + "start", + ["text","\t\t"], + ["keyword","do"], + ["text"," "], + ["keyword","ensure"] +],[ + "start", + ["text","\t\t\t"], + ["identifier","name"], + ["text"," "], + ["keyword.operator","="], + ["text"," "], + ["constant.language","Void"] +],[ + "start", + ["text","\t\t"], + ["keyword","end"] +],[ + "start" +],[ + "start", + ["keyword","feature"], + ["text"," "], + ["comment.line.double-dash","-- Access"] +],[ + "start" +],[ + "start", + ["text","\t"], + ["identifier","name"], + ["keyword.operator",":"], + ["text"," "], + ["keyword","detachable"], + ["text"," "], + ["entity.name.type","STRING"] +],[ + "start", + ["text","\t\t\t"], + ["comment.line.double-dash","-- Full name or Void if unknown."] +],[ + "start" +],[ + "start", + ["keyword","end"] +]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_elm.json b/lib/ace/mode/_test/tokens_elm.json new file mode 100644 index 00000000..b39de92f --- /dev/null +++ b/lib/ace/mode/_test/tokens_elm.json @@ -0,0 +1,198 @@ +[[ + "start", + ["comment.start","{-"], + ["comment"," Ace "], + ["comment.start","{-"], + ["comment"," 4 "], + ["comment.end","-}"], + ["comment"," Elm "], + ["comment.end","-}"] +],[ + "start", + ["constant.language","main"], + ["text"," "], + ["keyword","="], + ["text"," "], + ["identifier","lift"], + ["text"," "], + ["identifier","clock"], + ["text"," "], + ["paren.lparen","("], + ["identifier","every"], + ["text"," "], + ["identifier","second"], + ["paren.rparen",")"] +],[ + "start" +],[ + "start", + ["constant.language","clock"], + ["text"," "], + ["identifier","t"], + ["text"," "], + ["keyword","="], + ["text"," "], + ["identifier","collage"], + ["text"," "], + ["constant.numeric","400"], + ["text"," "], + ["constant.numeric","400"], + ["text"," "], + ["paren.lparen","["], + ["text"," "], + ["identifier","filled"], + ["text"," "], + ["identifier","lightGrey"], + ["text"," "], + ["paren.lparen","("], + ["identifier","ngon"], + ["text"," "], + ["constant.numeric","12"], + ["text"," "], + ["constant.numeric","110"], + ["paren.rparen",")"] +],[ + "start", + ["text"," "], + ["operator.punctuation",","], + ["text"," "], + ["identifier","outlined"], + ["text"," "], + ["paren.lparen","("], + ["identifier","solid"], + ["text"," "], + ["identifier","grey"], + ["paren.rparen",")"], + ["text"," "], + ["paren.lparen","("], + ["identifier","ngon"], + ["text"," "], + ["constant.numeric","12"], + ["text"," "], + ["constant.numeric","110"], + ["paren.rparen",")"] +],[ + "start", + ["text"," "], + ["operator.punctuation",","], + ["text"," "], + ["identifier","hand"], + ["text"," "], + ["identifier","orange"], + ["text"," "], + ["constant.numeric","100"], + ["text"," "], + ["identifier","t"] +],[ + "start", + ["text"," "], + ["operator.punctuation",","], + ["text"," "], + ["identifier","hand"], + ["text"," "], + ["identifier","charcoal"], + ["text"," "], + ["constant.numeric","100"], + ["text"," "], + ["paren.lparen","("], + ["identifier","t"], + ["keyword.operator","/"], + ["constant.numeric","60"], + ["paren.rparen",")"] +],[ + "start", + ["text"," "], + ["operator.punctuation",","], + ["text"," "], + ["identifier","hand"], + ["text"," "], + ["identifier","charcoal"], + ["text"," "], + ["constant.numeric","60"], + ["text"," "], + ["paren.lparen","("], + ["identifier","t"], + ["keyword.operator","/"], + ["constant.numeric","720"], + ["paren.rparen",")"], + ["text"," "], + ["paren.rparen","]"] +],[ + "start" +],[ + "start", + ["constant.language","hand"], + ["text"," "], + ["identifier","clr"], + ["text"," "], + ["identifier","len"], + ["text"," "], + ["identifier","time"], + ["text"," "], + ["keyword","="] +],[ + "start", + ["text"," "], + ["keyword","let"], + ["text"," "], + ["identifier","angle"], + ["text"," "], + ["keyword","="], + ["text"," "], + ["identifier","degrees"], + ["text"," "], + ["paren.lparen","("], + ["constant.numeric","90"], + ["text"," "], + ["keyword.operator","-"], + ["text"," "], + ["constant.numeric","6"], + ["text"," "], + ["keyword.operator","*"], + ["text"," "], + ["identifier","inSeconds"], + ["text"," "], + ["identifier","time"], + ["paren.rparen",")"] +],[ + "start", + ["text"," "], + ["keyword","in"], + ["text"," "], + ["identifier","traced"], + ["text"," "], + ["paren.lparen","("], + ["identifier","solid"], + ["text"," "], + ["identifier","clr"], + ["paren.rparen",")"], + ["text"," "], + ["keyword.operator","<|"], + ["text"," "], + ["identifier","segment"], + ["text"," "], + ["paren.lparen","("], + ["constant.numeric","0"], + ["operator.punctuation",","], + ["constant.numeric","0"], + ["paren.rparen",")"], + ["text"," "], + ["paren.lparen","("], + ["identifier","len"], + ["text"," "], + ["keyword.operator","*"], + ["text"," "], + ["identifier","cos"], + ["text"," "], + ["identifier","angle"], + ["operator.punctuation",","], + ["text"," "], + ["identifier","len"], + ["text"," "], + ["keyword.operator","*"], + ["text"," "], + ["identifier","sin"], + ["text"," "], + ["identifier","angle"], + ["paren.rparen",")"] +]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_gcode.json b/lib/ace/mode/_test/tokens_gcode.json new file mode 100644 index 00000000..d6227473 --- /dev/null +++ b/lib/ace/mode/_test/tokens_gcode.json @@ -0,0 +1,296 @@ +[[ + "start", + ["identifier","O"], + ["constant.numeric","003"], + ["text"," "], + ["comment","(DIAMOND SQUARE)"] +],[ + "start", + ["comment","N2"], + ["text"," "], + ["string","G54"], + ["text"," "], + ["string","G90"], + ["text"," "], + ["string","G49"], + ["text"," "], + ["string","G80"] +],[ + "start", + ["comment","N3"], + ["text"," "], + ["string","M6"], + ["text"," "], + ["identifier","T"], + ["constant.numeric","1"], + ["text"," "], + ["comment","(1.ENDMILL)"] +],[ + "start", + ["comment","N4"], + ["text"," "], + ["string","M3"], + ["text"," "], + ["identifier","S"], + ["constant.numeric","1800"] +],[ + "start", + ["comment","N5"], + ["text"," "], + ["string","G0"], + ["text"," "], + ["identifier","X"], + ["constant.numeric","-.6"], + ["text"," "], + ["identifier","Y"], + ["constant.numeric","2.050"] +],[ + "start", + ["comment","N6"], + ["text"," "], + ["string","G43"], + ["text"," "], + ["identifier","H"], + ["constant.numeric","1"], + ["text"," "], + ["identifier","Z"], + ["constant.numeric",".1"] +],[ + "start", + ["comment","N7"], + ["text"," "], + ["string","G1"], + ["text"," "], + ["identifier","Z"], + ["constant.numeric","-.3"], + ["text"," "], + ["identifier","F"], + ["constant.numeric","50."] +],[ + "start", + ["comment","N8"], + ["text"," "], + ["string","G41"], + ["text"," "], + ["identifier","D"], + ["constant.numeric","1"], + ["text"," "], + ["identifier","Y"], + ["constant.numeric","1.45"] +],[ + "start", + ["comment","N9"], + ["text"," "], + ["string","G1"], + ["text"," "], + ["identifier","X"], + ["constant.numeric","0"], + ["text"," "], + ["identifier","F"], + ["constant.numeric","20."] +],[ + "start", + ["comment","N10"], + ["text"," "], + ["string","G2"], + ["text"," "], + ["identifier","J"], + ["constant.numeric","-1.45"] +],[ + "start", + ["comment","(CUTTER COMP CANCEL)"] +],[ + "start", + ["comment","N11"], + ["text"," "], + ["string","G1"], + ["text"," "], + ["identifier","Z"], + ["constant.numeric","-.2"], + ["text"," "], + ["identifier","F"], + ["constant.numeric","50."] +],[ + "start", + ["comment","N12"], + ["text"," "], + ["identifier","Y"], + ["constant.numeric","-.990"] +],[ + "start", + ["comment","N13"], + ["text"," "], + ["string","G40"] +],[ + "start", + ["comment","N14"], + ["text"," "], + ["string","G0"], + ["text"," "], + ["identifier","X"], + ["constant.numeric","-.6"], + ["text"," "], + ["identifier","Y"], + ["constant.numeric","1.590"] +],[ + "start", + ["comment","N15"], + ["text"," "], + ["string","G0"], + ["text"," "], + ["identifier","Z"], + ["constant.numeric",".1"] +],[ + "start", + ["comment","N16"], + ["text"," "], + ["string","M5"], + ["text"," "], + ["string","G49"], + ["text"," "], + ["string","G28"], + ["text"," "], + ["string","G91"], + ["text"," "], + ["identifier","Z"], + ["constant.numeric","0"] +],[ + "start", + ["comment","N17"], + ["text"," "], + ["identifier","CALL"], + ["text"," "], + ["identifier","O"], + ["constant.numeric","9456"] +],[ + "start", + ["comment","N18"], + ["text"," #"], + ["constant.numeric","500"], + ["text","="], + ["constant.numeric","0.004"] +],[ + "start", + ["comment","N19"], + ["text"," #"], + ["constant.numeric","503"], + ["text","="], + ["paren.lparen","["], + ["text","#"], + ["constant.numeric","500"], + ["text","+#"], + ["constant.numeric","501"], + ["paren.rparen","]"] +],[ + "start", + ["comment","N20"], + ["text"," "], + ["identifier","VC"], + ["constant.numeric","45"], + ["text","="], + ["constant.numeric","0.0006"] +],[ + "start", + ["identifier","VS"], + ["constant.numeric","4"], + ["text","="], + ["constant.numeric","0.0007"] +],[ + "start", + ["comment","N21"], + ["text"," "], + ["string","G90"], + ["text"," "], + ["string","G10"], + ["text"," "], + ["identifier","L"], + ["constant.numeric","20"], + ["text"," "], + ["identifier","P"], + ["constant.numeric","3"], + ["text"," "], + ["identifier","X"], + ["constant.numeric","5."], + ["identifier","Y"], + ["constant.numeric","4."], + ["text"," "], + ["identifier","Z"], + ["constant.numeric","6.567"] +],[ + "start", + ["comment","N22"], + ["text"," "], + ["string","G0"], + ["text"," "], + ["identifier","X"], + ["constant.numeric","5000"] +],[ + "start", + ["comment","N23"], + ["text"," "], + ["identifier","IF"], + ["text"," "], + ["paren.lparen","["], + ["text","#"], + ["constant.numeric","1"], + ["text"," "], + ["identifier","LT"], + ["text"," "], + ["constant.numeric","0.370"], + ["paren.rparen","]"], + ["text"," "], + ["identifier","GOTO"], + ["text"," "], + ["constant.numeric","49"] +],[ + "start", + ["comment","N24"], + ["text"," "], + ["identifier","X"], + ["constant.numeric","-0.678"], + ["text"," "], + ["identifier","Y"], + ["constant.numeric","+.990"] +],[ + "start", + ["comment","N25"], + ["text"," "], + ["string","G84.3"], + ["text"," "], + ["identifier","X"], + ["constant.numeric","-0.1"] +],[ + "start", + ["comment","N26"], + ["text"," #"], + ["constant.numeric","4"], + ["text","=#"], + ["constant.numeric","5"], + ["text","*"], + ["identifier","COS"], + ["paren.lparen","["], + ["constant.numeric","45"], + ["paren.rparen","]"] +],[ + "start", + ["comment","N27"], + ["text"," #"], + ["constant.numeric","4"], + ["text","=#"], + ["constant.numeric","5"], + ["text","*"], + ["identifier","SIN"], + ["paren.lparen","["], + ["constant.numeric","45"], + ["paren.rparen","]"] +],[ + "start", + ["comment","N28"], + ["text"," "], + ["identifier","VZOFZ"], + ["text","="], + ["constant.numeric","652.9658"] +],[ + "start", + ["text","%"] +]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_html_ruby.json b/lib/ace/mode/_test/tokens_html_ruby.json index 2c74ba56..8ff5f6ea 100644 --- a/lib/ace/mode/_test/tokens_html_ruby.json +++ b/lib/ace/mode/_test/tokens_html_ruby.json @@ -144,7 +144,9 @@ ["text"," "], ["support.function","link_to"], ["text"," "], - ["string","'Show'"], + ["string.start","'"], + ["string","Show"], + ["string.end","'"], ["text",", "], ["identifier","book"], ["text"," "], @@ -162,7 +164,9 @@ ["text"," "], ["support.function","link_to"], ["text"," "], - ["string","'Edit'"], + ["string.start","'"], + ["string","Edit"], + ["string.end","'"], ["text",", "], ["identifier","edit_book_path"], ["paren.lparen","("], @@ -183,7 +187,9 @@ ["text"," "], ["support.function","link_to"], ["text"," "], - ["string","'Remove'"], + ["string.start","'"], + ["string","Remove"], + ["string.end","'"], ["text",", "], ["identifier","book"], ["text",", "], @@ -191,7 +197,9 @@ ["text"," "], ["punctuation.separator.key-value","=>"], ["text"," "], - ["string","'Are you sure?'"], + ["string.start","'"], + ["string","Are you sure?"], + ["string.end","'"], ["text",", "], ["constant.other.symbol.ruby",":method"], ["text"," "], @@ -239,7 +247,9 @@ ["text"," "], ["support.function","link_to"], ["text"," "], - ["string","'New book'"], + ["string.start","'"], + ["string","New book"], + ["string.end","'"], ["text",", "], ["identifier","new_book_path"], ["text"," "], diff --git a/lib/ace/mode/_test/tokens_io.json b/lib/ace/mode/_test/tokens_io.json new file mode 100644 index 00000000..b83a675a --- /dev/null +++ b/lib/ace/mode/_test/tokens_io.json @@ -0,0 +1,49 @@ +[[ + "start", + ["punctuation.definition.comment.io","//"], + ["comment.line.double-slash.io"," computes factorial of a number"] +],[ + "start", + ["text","factorial "], + ["keyword.operator.io",":="], + ["text"," "], + ["support.function.io","method"], + ["text","(n,"] +],[ + "start", + ["text"," "], + ["keyword.control.io","if"], + ["text","(n "], + ["keyword.operator.io","=="], + ["text"," "], + ["constant.numeric.io","0"], + ["text",", "], + ["keyword.control.io","return"], + ["text"," "], + ["constant.numeric.io","1"], + ["text",")"] +],[ + "start", + ["text"," res "], + ["keyword.operator.io",":="], + ["text"," "], + ["constant.numeric.io","1"] +],[ + "start", + ["text"," "], + ["support.class.io","Range"], + ["text"," "], + ["constant.numeric.io","1"], + ["text"," "], + ["support.function.io","to"], + ["text","(n) "], + ["keyword.control.io","foreach"], + ["text","(i, res "], + ["keyword.operator.io","="], + ["text"," res "], + ["keyword.operator.io","*"], + ["text"," i)"] +],[ + "start", + ["text",")"] +]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_jsoniq.json b/lib/ace/mode/_test/tokens_jsoniq.json new file mode 100644 index 00000000..0f4ee6e9 --- /dev/null +++ b/lib/ace/mode/_test/tokens_jsoniq.json @@ -0,0 +1,4 @@ +[[ + "[\"start\"]", + ["support.function","TODO"] +]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_matlab.json b/lib/ace/mode/_test/tokens_matlab.json index 9909eadd..6b4a8567 100644 --- a/lib/ace/mode/_test/tokens_matlab.json +++ b/lib/ace/mode/_test/tokens_matlab.json @@ -1,4 +1,90 @@ [[ + ["blockComment","noQstring"], + ["comment.start","%{"] +],[ + ["blockComment","blockComment","blockComment","noQstring"], + ["comment.start"," %{"] +],[ + ["blockComment","blockComment","blockComment","noQstring"], + ["comment"," Ace Matlab demo"] +],[ + ["blockComment","noQstring"], + ["comment.end"," %}"] +],[ + "noQstring", + ["comment.end","%}"] +],[ + "start" +],[ "start", - ["identifier","TODO"] + ["keyword","classdef"], + ["text"," "], + ["identifier","hello"] +],[ + "start", + ["text"," "], + ["support.function","methods"] +],[ + "start", + ["text"," "], + ["keyword","function"], + ["text"," "], + ["identifier","greet"], + ["paren.lparen","("], + ["identifier","this"], + ["paren.rparen",")"] +],[ + "start", + ["text"," "], + ["support.function","disp"], + ["paren.lparen","("], + ["string","'Hello!'"], + ["paren.rparen",")"], + ["text"," "], + ["comment","% say hi"] +],[ + "start", + ["text"," "], + ["keyword","end"] +],[ + "start", + ["text"," "], + ["keyword","end"] +],[ + "start", + ["keyword","end"] +],[ + "noQstring" +],[ + "start", + ["comment","% transpose "] +],[ + "qqstring", + ["identifier","a"], + ["text"," "], + ["keyword.operator","="], + ["text"," "], + ["paren.lparen","["], + ["text"," "], + ["string","'x"], + ["constant.language.escape","''"], + ["string","y'"], + ["punctuation.operator",","], + ["text"," "], + ["string","\"x"], + ["constant.language.escape","\\n"], + ["string","\\"] +],[ + "start", + ["string"," y\""], + ["punctuation.operator",","], + ["text"," "], + ["constant.numeric","1"], + ["text","' "], + ["paren.rparen","]"], + ["text","' "], + ["keyword.operator","+"], + ["text"," "], + ["constant.numeric","2"], + ["text","'"] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_ruby.json b/lib/ace/mode/_test/tokens_ruby.json index 19b98b70..1809f5ee 100644 --- a/lib/ace/mode/_test/tokens_ruby.json +++ b/lib/ace/mode/_test/tokens_ruby.json @@ -145,7 +145,9 @@ ["text"," "], ["punctuation.separator.key-value","=>"], ["text"," "], - ["string","\"value\""], + ["string.start","\""], + ["string","value"], + ["string.end","\""], ["paren.rparen","}"] ],[ "start" diff --git a/lib/ace/mode/_test/tokens_sh.json b/lib/ace/mode/_test/tokens_sh.json index 53411906..f2c6b276 100644 --- a/lib/ace/mode/_test/tokens_sh.json +++ b/lib/ace/mode/_test/tokens_sh.json @@ -331,4 +331,4 @@ ["keyword","fi"] ],[ "start" -]] +]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_soy_template.json b/lib/ace/mode/_test/tokens_soy_template.json index 46ea77fa..9ae7c4ed 100644 --- a/lib/ace/mode/_test/tokens_soy_template.json +++ b/lib/ace/mode/_test/tokens_soy_template.json @@ -157,13 +157,12 @@ ["text.xml"," "], ["punctuation.definition.tag.begin.soy","{"], ["entity.name.tag.soy","param"], - ["text"," "], + ["meta.tag.param.soy"," "], ["entity.other.attribute-name.soy","name"], ["keyword.operator.soy",":"], ["meta.tag.param.soy"," "], ["variable.other.soy","$additionalName"], - ["text"," "], - ["meta.tag.param.soy","/"], + ["meta.tag.param.soy"," /"], ["punctuation.definition.tag.end.soy","}"] ],[ "start", diff --git a/lib/ace/mode/_test/tokens_xquery.json b/lib/ace/mode/_test/tokens_xquery.json new file mode 100644 index 00000000..aaf9ab9b --- /dev/null +++ b/lib/ace/mode/_test/tokens_xquery.json @@ -0,0 +1,44 @@ +[[ + "[\"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/elixir.js b/lib/ace/mode/elixir.js new file mode 100644 index 00000000..c55ea366 --- /dev/null +++ b/lib/ace/mode/elixir.js @@ -0,0 +1,58 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2012, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +/* + THIS FILE WAS AUTOGENERATED BY mode.tmpl.js +*/ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var ElixirHighlightRules = require("./elixir_highlight_rules").ElixirHighlightRules; +// TODO: pick appropriate fold mode +var FoldMode = require("./folding/coffee").FoldMode; + +var Mode = function() { + this.HighlightRules = ElixirHighlightRules; + this.foldingRules = new FoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + this.lineCommentStart = "#"; + // this.blockComment = {start: ""/*"", end: ""*/""}; + // Extra logic goes here. + this.$id = "ace/mode/elixir" +}).call(Mode.prototype); + +exports.Mode = Mode; +}); \ No newline at end of file diff --git a/lib/ace/mode/elixir_highlight_rules.js b/lib/ace/mode/elixir_highlight_rules.js new file mode 100644 index 00000000..a13492be --- /dev/null +++ b/lib/ace/mode/elixir_highlight_rules.js @@ -0,0 +1,433 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2012, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +/* This file was autogenerated from https://raw.githubusercontent.com/elixir-lang/elixir-tmbundle/master/Syntaxes/Elixir.tmLanguage (uuid: ) */ +/**************************************************************************************** + * IT MIGHT NOT BE PERFECT ...But it's a good start from an existing *.tmlanguage file. * + * fileTypes * + ****************************************************************************************/ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var ElixirHighlightRules = function() { + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + + this.$rules = { start: + [ { token: + [ 'meta.module.elixir', + 'keyword.control.module.elixir', + 'meta.module.elixir', + 'entity.name.type.module.elixir' ], + regex: '^(\\s*)(defmodule)(\\s+)((?:[A-Z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)' }, + { token: 'comment.documentation.heredoc', + regex: '@(?:module|type)?doc (?:~[a-z])?"""', + push: + [ { token: 'comment.documentation.heredoc', + regex: '\\s*"""', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'comment.documentation.heredoc' } ], + comment: '@doc with heredocs is treated as documentation' }, + { token: 'comment.documentation.heredoc', + regex: '@(?:module|type)?doc ~[A-Z]"""', + push: + [ { token: 'comment.documentation.heredoc', + regex: '\\s*"""', + next: 'pop' }, + { defaultToken: 'comment.documentation.heredoc' } ], + comment: '@doc with heredocs is treated as documentation' }, + { token: 'comment.documentation.heredoc', + regex: '@(?:module|type)?doc (?:~[a-z])?\'\'\'', + push: + [ { token: 'comment.documentation.heredoc', + regex: '\\s*\'\'\'', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'comment.documentation.heredoc' } ], + comment: '@doc with heredocs is treated as documentation' }, + { token: 'comment.documentation.heredoc', + regex: '@(?:module|type)?doc ~[A-Z]\'\'\'', + push: + [ { token: 'comment.documentation.heredoc', + regex: '\\s*\'\'\'', + next: 'pop' }, + { defaultToken: 'comment.documentation.heredoc' } ], + comment: '@doc with heredocs is treated as documentation' }, + { token: 'comment.documentation.false', + regex: '@(?:module|type)?doc false', + comment: '@doc false is treated as documentation' }, + { token: 'comment.documentation.string', + regex: '@(?:module|type)?doc "', + push: + [ { token: 'comment.documentation.string', + regex: '"', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'comment.documentation.string' } ], + comment: '@doc with string is treated as documentation' }, + { token: 'keyword.control.elixir', + regex: '\\b(?:do|end|case|bc|lc|for|if|cond|unless|try|receive|fn|defmodule|defp?|defprotocol|defimpl|defrecord|defstruct|defmacrop?|defdelegate|defcallback|defmacrocallback|defexception|defoverridable|exit|after|rescue|catch|else|raise|throw|import|require|alias|use|quote|unquote|super)\\b(?![?!])', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?_?\\h)*|\\d(?>_?\\d)*(\\.(?![^[:space:][:digit:]])(?>_?\\d)*)?([eE][-+]?\\d(?>_?\\d)*)?|0b[01]+|0o[0-7]+)\\b' }, + { token: 'punctuation.definition.constant.elixir', + regex: ':\'', + push: + [ { token: 'punctuation.definition.constant.elixir', + regex: '\'', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'constant.other.symbol.single-quoted.elixir' } ] }, + { token: 'punctuation.definition.constant.elixir', + regex: ':"', + push: + [ { token: 'punctuation.definition.constant.elixir', + regex: '"', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'constant.other.symbol.double-quoted.elixir' } ] }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '(?:\'\'\')', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?>\'\'\')', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '^\\s*\'\'\'', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'support.function.variable.quoted.single.heredoc.elixir' } ], + comment: 'Single-quoted heredocs' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '\'', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\'', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'support.function.variable.quoted.single.elixir' } ], + comment: 'single quoted string (allows for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '(?:""")', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?>""")', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '^\\s*"""', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.quoted.double.heredoc.elixir' } ], + comment: 'Double-quoted heredocs' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '"', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '"', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.quoted.double.elixir' } ], + comment: 'double quoted string (allows for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z](?:""")', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '~[a-z](?>""")', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '^\\s*"""', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.quoted.double.heredoc.elixir' } ], + comment: 'Double-quoted heredocs sigils' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z]\\{', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\}[a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z]\\[', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\][a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z]\\<', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\>[a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z]\\(', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\)[a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z][^\\w]', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '[^\\w][a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z](?:""")', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '~[A-Z](?>""")', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '^\\s*"""', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'Double-quoted heredocs sigils' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z]\\{', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\}[a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z]\\[', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\][a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z]\\<', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\>[a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z]\\(', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\)[a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z][^\\w]', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '[^\\w][a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: ['punctuation.definition.constant.elixir', 'constant.other.symbol.elixir'], + regex: '(:)([a-zA-Z_][\\w@]*(?:[?!]|=(?![>=]))?|\\<\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\-|\\|>|=>|~|~=|=|/|\\\\\\\\|\\*\\*?|\\.\\.?\\.?|>=?|<=?|&&?&?|\\+\\+?|\\-\\-?|\\|\\|?\\|?|\\!|@|\\%?\\{\\}|%|\\[\\]|\\^(?:\\^\\^)?)', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?[a-zA-Z_][\\w@]*(?>[?!]|=(?![>=]))?|\\<\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\-|\\|>|=>|~|~=|=|/|\\\\\\\\|\\*\\*?|\\.\\.?\\.?|>=?|<=?|&&?&?|\\+\\+?|\\-\\-?|\\|\\|?\\|?|\\!|@|\\%?\\{\\}|%|\\[\\]|\\^(\\^\\^)?)', + comment: 'symbols' }, + { token: 'punctuation.definition.constant.elixir', + regex: '(?:[a-zA-Z_][\\w@]*(?:[?!])?):(?!:)', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?>[a-zA-Z_][\\w@]*(?>[?!])?)(:)(?!:)', + comment: 'symbols' }, + { token: + [ 'punctuation.definition.comment.elixir', + 'comment.line.number-sign.elixir' ], + regex: '(#)(.*)' }, + { token: 'constant.numeric.elixir', + regex: '\\?(?:\\\\(?:x[\\da-fA-F]{1,2}(?![\\da-fA-F])\\b|[^xMC])|[^\\s\\\\])', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?=?' }, + { token: 'keyword.operator.bitwise.elixir', + regex: '\\|{3}|&{3}|\\^{3}|<{3}|>{3}|~{3}' }, + { token: 'keyword.operator.logical.elixir', + regex: '!+|\\bnot\\b|&&|\\band\\b|\\|\\||\\bor\\b|\\bxor\\b', + originalRegex: '(?<=[ \\t])!+|\\bnot\\b|&&|\\band\\b|\\|\\||\\bor\\b|\\bxor\\b' }, + { token: 'keyword.operator.arithmetic.elixir', + regex: '\\*|\\+|\\-|/' }, + { token: 'keyword.operator.other.elixir', + regex: '\\||\\+\\+|\\-\\-|\\*\\*|\\\\\\\\|\\<\\-|\\<\\>|\\<\\<|\\>\\>|\\:\\:|\\.\\.|\\|>|~|=>' }, + { token: 'keyword.operator.assignment.elixir', regex: '=' }, + { token: 'punctuation.separator.other.elixir', regex: ':' }, + { token: 'punctuation.separator.statement.elixir', + regex: '\\;' }, + { token: 'punctuation.separator.object.elixir', regex: ',' }, + { token: 'punctuation.separator.method.elixir', regex: '\\.' }, + { token: 'punctuation.section.scope.elixir', regex: '\\{|\\}' }, + { token: 'punctuation.section.array.elixir', regex: '\\[|\\]' }, + { token: 'punctuation.section.function.elixir', + regex: '\\(|\\)' } ], + '#escaped_char': + [ { token: 'constant.character.escape.elixir', + regex: '\\\\(?:x[\\da-fA-F]{1,2}|.)' } ], + '#interpolated_elixir': + [ { token: + [ 'source.elixir.embedded.source', + 'source.elixir.embedded.source.empty' ], + regex: '(#\\{)(\\})' }, + { todo: + { token: 'punctuation.section.embedded.elixir', + regex: '#\\{', + push: + [ { token: 'punctuation.section.embedded.elixir', + regex: '\\}', + next: 'pop' }, + { include: '#nest_curly_and_self' }, + { include: '$self' }, + { defaultToken: 'source.elixir.embedded.source' } ] } } ], + '#nest_curly_and_self': + [ { token: 'punctuation.section.scope.elixir', + regex: '\\{', + push: + [ { token: 'punctuation.section.scope.elixir', + regex: '\\}', + next: 'pop' }, + { include: '#nest_curly_and_self' } ] }, + { include: '$self' } ], + '#regex_sub': + [ { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { token: + [ 'punctuation.definition.arbitrary-repitition.elixir', + 'string.regexp.arbitrary-repitition.elixir', + 'string.regexp.arbitrary-repitition.elixir', + 'punctuation.definition.arbitrary-repitition.elixir' ], + regex: '(\\{)(\\d+)((?:,\\d+)?)(\\})' }, + { token: 'punctuation.definition.character-class.elixir', + regex: '\\[(?:\\^?\\])?', + push: + [ { token: 'punctuation.definition.character-class.elixir', + regex: '\\]', + next: 'pop' }, + { include: '#escaped_char' }, + { defaultToken: 'string.regexp.character-class.elixir' } ] }, + { token: 'punctuation.definition.group.elixir', + regex: '\\(', + push: + [ { token: 'punctuation.definition.group.elixir', + regex: '\\)', + next: 'pop' }, + { include: '#regex_sub' }, + { defaultToken: 'string.regexp.group.elixir' } ] }, + { token: + [ 'punctuation.definition.comment.elixir', + 'comment.line.number-sign.elixir' ], + regex: '(?:^|\\s)(#)(\\s[[a-zA-Z0-9,. \\t?!-][^\\x00-\\x7F]]*$)', + originalRegex: '(?<=^|\\s)(#)\\s[[a-zA-Z0-9,. \\t?!-][^\\x{00}-\\x{7F}]]*$', + comment: 'We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.' } ] } + + this.normalizeRules(); +}; + +ElixirHighlightRules.metaData = { comment: 'Textmate bundle for Elixir Programming Language.', + fileTypes: [ 'ex', 'exs' ], + firstLineMatch: '^#!/.*\\belixir', + foldingStartMarker: '(after|else|catch|rescue|\\-\\>|\\{|\\[|do)\\s*$', + foldingStopMarker: '^\\s*((\\}|\\]|after|else|catch|rescue)\\s*$|end\\b)', + keyEquivalent: '^~E', + name: 'Elixir', + scopeName: 'source.elixir' } + + +oop.inherits(ElixirHighlightRules, TextHighlightRules); + +exports.ElixirHighlightRules = ElixirHighlightRules; +}); \ No newline at end of file diff --git a/lib/ace/mode/jsoniq.js b/lib/ace/mode/jsoniq.js index 6f10d2d3..64dc9541 100644 --- a/lib/ace/mode/jsoniq.js +++ b/lib/ace/mode/jsoniq.js @@ -39,7 +39,6 @@ var Range = require("../range").Range; var XQueryBehaviour = require("./behaviour/xquery").XQueryBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Anchor = require("../anchor").Anchor; -var LanguageTools = require("../ext/language_tools"); var Mode = function() { this.$tokenizer = new JSONiqLexer(); @@ -52,14 +51,16 @@ oop.inherits(Mode, TextMode); (function() { - LanguageTools.addCompleter({ + this.completer = { getCompletions: function(editor, session, pos, prefix, callback) { + if (!session.$worker) + return callback(); session.$worker.emit("complete", { data: { pos: pos, prefix: prefix } }); session.$worker.on("complete", function(e){ callback(null, e.data); }); } - }); + }; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); diff --git a/lib/ace/mode/ruby_highlight_rules.js b/lib/ace/mode/ruby_highlight_rules.js index 13dcd1b2..a1cb12f9 100644 --- a/lib/ace/mode/ruby_highlight_rules.js +++ b/lib/ace/mode/ruby_highlight_rules.js @@ -141,9 +141,71 @@ var RubyHighlightRules = function() { regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)" }, - qString, - qqString, - tString, + [{ + regex: "[{}]", onMatch: function(val, state, stack) { + this.next = val == "{" ? this.nextState : ""; + if (val == "{" && stack.length) { + stack.unshift("start", state); + return "paren.lparen"; + } + if (val == "}" && stack.length) { + stack.shift(); + this.next = stack.shift(); + if (this.next.indexOf("string") != -1) + return "paren.end"; + } + return val == "{" ? "paren.lparen" : "paren.rparen"; + }, + nextState: "start" + }, { + token : "string.start", + regex : /"/, + push : [{ + token : "constant.language.escape", + regex : /\\(?:[nsrtvfbae'"\\]|c.|C-.|M-.(?:\\C-.)?|[0-7]{3}|x[\da-fA-F]{2}|u[\da-fA-F]{4})/ + }, { + token : "paren.start", + regex : /\#{/, + push : "start" + }, { + token : "string.end", + regex : /"/, + next : "pop" + }, { + defaultToken: "string" + }] + }, { + token : "string.start", + regex : /`/, + push : [{ + token : "constant.language.escape", + regex : /\\(?:[nsrtvfbae'"\\]|c.|C-.|M-.(?:\\C-.)?|[0-7]{3}|x[\da-fA-F]{2}|u[\da-fA-F]{4})/ + }, { + token : "paren.start", + regex : /\#{/, + push : "start" + }, { + token : "string.end", + regex : /`/, + next : "pop" + }, { + defaultToken: "string" + }] + }, { + token : "string.start", + regex : /'/, + push : [{ + token : "constant.language.escape", + regex : /\\['\\]/ + }, { + token : "string.end", + regex : /'/, + next : "pop" + }, { + defaultToken: "string" + }] + }], + // TODO: add support for %[QqxWwrs][{[(] { token : "text", // namespaces aren't symbols diff --git a/lib/ace/mode/rust_highlight_rules.js b/lib/ace/mode/rust_highlight_rules.js index 1a7d38a6..422e8e80 100644 --- a/lib/ace/mode/rust_highlight_rules.js +++ b/lib/ace/mode/rust_highlight_rules.js @@ -127,10 +127,14 @@ var RustHighlightRules = function() { regex: '$', next: 'pop' }, { defaultToken: 'comment.line.double-dash.source.rust' } ] }, - { token: 'comment.block.source.rust', + { token: 'comment.start.block.source.rust', regex: '/\\*', + stateName: 'comment', push: - [ { token: 'comment.block.source.rust', + [ { token: 'comment.start.block.source.rust', + regex: '/\\*', + push: 'comment' }, + { token: 'comment.end.block.source.rust', regex: '\\*/', next: 'pop' }, { defaultToken: 'comment.block.source.rust' } ] } ], diff --git a/lib/ace/mode/soy_template_highlight_rules.js b/lib/ace/mode/soy_template_highlight_rules.js index 50e3ae48..aa913fac 100644 --- a/lib/ace/mode/soy_template_highlight_rules.js +++ b/lib/ace/mode/soy_template_highlight_rules.js @@ -188,7 +188,7 @@ var SoyTemplateHighlightRules = function() { [ 'entity.other.attribute-name.soy', 'text', 'keyword.operator.soy' ], - regex: '\\b([\\w]*)(\\s*)((?::)?)' }, + regex: '\\b([\\w]+)(\\s*)((?::)?)' }, { defaultToken: 'meta.tag.param.soy' } ] } ], '#primitive': [ { token: 'constant.language.soy', diff --git a/lib/ace/mode/xquery.js b/lib/ace/mode/xquery.js index b93d61d2..024a5c6a 100644 --- a/lib/ace/mode/xquery.js +++ b/lib/ace/mode/xquery.js @@ -39,7 +39,6 @@ var Range = require("../range").Range; var XQueryBehaviour = require("./behaviour/xquery").XQueryBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Anchor = require("../anchor").Anchor; -var LanguageTools = require("../ext/language_tools"); var Mode = function() { this.$tokenizer = new XQueryLexer(); @@ -51,14 +50,16 @@ oop.inherits(Mode, TextMode); (function() { - LanguageTools.addCompleter({ + this.completer = { getCompletions: function(editor, session, pos, prefix, callback) { + if (!session.$worker) + return callback(); session.$worker.emit("complete", { data: { pos: pos, prefix: prefix } }); session.$worker.on("complete", function(e){ callback(null, e.data); }); } - }); + }; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); diff --git a/lib/ace/snippets/dockerfile.js b/lib/ace/snippets/dockerfile.js new file mode 100644 index 00000000..057347fb --- /dev/null +++ b/lib/ace/snippets/dockerfile.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./dockerfile.snippets"); +exports.scope = "dockerfile"; + +}); diff --git a/lib/ace/snippets/dockerfile.snippets b/lib/ace/snippets/dockerfile.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/snippets/dummy.js b/lib/ace/snippets/dummy.js new file mode 100644 index 00000000..359d9103 --- /dev/null +++ b/lib/ace/snippets/dummy.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./.snippets"); +exports.scope = ""; + +}); diff --git a/lib/ace/snippets/dummy_syntax.js b/lib/ace/snippets/dummy_syntax.js new file mode 100644 index 00000000..359d9103 --- /dev/null +++ b/lib/ace/snippets/dummy_syntax.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./.snippets"); +exports.scope = ""; + +}); diff --git a/lib/ace/snippets/eiffel.js b/lib/ace/snippets/eiffel.js new file mode 100644 index 00000000..04f4c5a9 --- /dev/null +++ b/lib/ace/snippets/eiffel.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./eiffel.snippets"); +exports.scope = "eiffel"; + +}); diff --git a/lib/ace/snippets/eiffel.snippets b/lib/ace/snippets/eiffel.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/snippets/elm.js b/lib/ace/snippets/elm.js new file mode 100644 index 00000000..44f18c11 --- /dev/null +++ b/lib/ace/snippets/elm.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./elm.snippets"); +exports.scope = "elm"; + +}); diff --git a/lib/ace/snippets/elm.snippets b/lib/ace/snippets/elm.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/snippets/io.snippets b/lib/ace/snippets/io.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/snippets/vala.snippets b/lib/ace/snippets/vala.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/tokenizer.js b/lib/ace/tokenizer.js index e947a130..a0756157 100644 --- a/lib/ace/tokenizer.js +++ b/lib/ace/tokenizer.js @@ -32,7 +32,7 @@ define(function(require, exports, module) { "use strict"; // tokenizing lines longer than this makes editor very slow -var MAX_TOKEN_COUNT = 1000; +var MAX_TOKEN_COUNT = 2000; /** * This class takes a set of highlighting rules, and creates a tokenizer out of them. For more information, see [the wiki on extending highlighters](https://github.com/ajaxorg/ace/wiki/Creating-or-Extending-an-Edit-Mode#wiki-extendingTheHighlighter). * @class Tokenizer @@ -77,9 +77,11 @@ var Tokenizer = function(rules) { if (rule.token.length == 1 || matchcount == 1) { rule.token = rule.token[0]; } else if (matchcount - 1 != rule.token.length) { - throw new Error("number of classes and regexp groups in '" + - rule.token + "'\n'" + rule.regex + "' doesn't match\n" - + (matchcount - 1) + "!=" + rule.token.length); + this.reportError("number of classes and regexp groups doesn't match", { + rule: rule, + groupCount: matchcount - 1 + }); + rule.token = rule.token[0]; } else { rule.tokenArray = rule.token; rule.token = null; @@ -240,6 +242,7 @@ var Tokenizer = function(rules) { var match, tokens = []; var lastIndex = 0; + var matchAttempts = 0; var token = {type: null, value: ""}; @@ -280,7 +283,7 @@ var Tokenizer = function(rules) { state = this.states[currentState]; if (!state) { - window.console && console.error && console.error(currentState, "doesn't exist"); + this.reportError("state doesn't exist", currentState); currentState = "start"; state = this.states[currentState]; } @@ -293,7 +296,7 @@ var Tokenizer = function(rules) { } if (value) { - if (typeof type == "string") { + if (typeof type === "string") { if ((!rule || rule.merge !== false) && token.type === type) { token.value += value; } else { @@ -315,7 +318,13 @@ var Tokenizer = function(rules) { lastIndex = index; - if (tokens.length > MAX_TOKEN_COUNT) { + if (matchAttempts++ > MAX_TOKEN_COUNT) { + if (matchAttempts > 2 * line.length) { + this.reportError("infinite loop with in ace tokenizer", { + startState: startState, + line: line + }); + } // chrome doens't show contents of text nodes with very long text while (lastIndex < line.length) { if (token.type) @@ -343,7 +352,14 @@ var Tokenizer = function(rules) { state : stack.length ? stack : currentState }; }; - + + this.reportError = function(msg, data) { + var e = new Error(msg); + e.data = data; + if (typeof console == "object" && console.error) + console.error(e); + setTimeout(function() { throw e; }); + }; }).call(Tokenizer.prototype); exports.Tokenizer = Tokenizer; diff --git a/lib/ace/tokenizer_test.js b/lib/ace/tokenizer_test.js index 281f58b3..41bf01c8 100644 --- a/lib/ace/tokenizer_test.js +++ b/lib/ace/tokenizer_test.js @@ -29,7 +29,7 @@ * ***** END LICENSE BLOCK ***** */ if (typeof process !== "undefined") { - require("amd-loader"); + require("amd-loader"); } define(function(require, exports, module) { @@ -59,7 +59,35 @@ module.exports = { var t = new Tokenizer({}); var re = t.removeCapturingGroups("(ax(by))[()]"); assert.equal(re, "(?:ax(?:by))[()]"); - } + }, + + "test: broken highlight rules": function() { + var t = new Tokenizer({ + start: [{ + token: 's', + regex: '&&&|^^^' + }, { + defaultToken: "def" + }], + state1: [{ + token: 'x', + regex: /\b([\w]*)(\s*)((?::)?)/ + }] + }); + var errorReports = 0; + t.reportError = function() { errorReports++; }; + var tokens = t.getLineTokens("x|", "start"); + assert.deepEqual(tokens, { + tokens: [{value: 'x|', type: 'overflow'}], + state: 'start' + }); + var tokens = t.getLineTokens("x|", "state1"); + assert.deepEqual(tokens, { + tokens: [{value: 'x', type: 'x'}, {value: '|', type: 'overflow'}], + state: 'start' + }); + assert.equal(errorReports, 2); + }, }; }); diff --git a/package.json b/package.json index 9734fc52..e7a166dc 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "jsdom": "0.2.x", "amd-loader": "~0.0.4", "dryice": "0.4.11", - "architect-build": "https://github.com/c9/architect-build/tarball/42723e152bb" + "architect-build": "https://github.com/c9/architect-build/tarball/a3bad51808" }, "mappings": { "ace": "." diff --git a/tool/tmlanguage.js b/tool/tmlanguage.js index d3e42141..9261a2f1 100644 --- a/tool/tmlanguage.js +++ b/tool/tmlanguage.js @@ -107,7 +107,7 @@ function convertToNonCapturingGroups(str) { function simplifyNonCapturingGroups(str) { var tokens = tokenize(str); - var t = tokens[0]; + var t = tokens[0] || {}; if (t.type == "group.start" && t.value == "(?:" && t.end == last(tokens)) { t.value = t.end.value = "";