0
|
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
2 // Distributed under an MIT license: https://codemirror.net/5/LICENSE
|
|
3
|
|
4 (function(mod) {
|
|
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
6 mod(require("../../lib/codemirror"), require("../clike/clike"));
|
|
7 else if (typeof define == "function" && define.amd) // AMD
|
|
8 define(["../../lib/codemirror", "../clike/clike"], mod);
|
|
9 else // Plain browser env
|
|
10 mod(CodeMirror);
|
|
11 })(function(CodeMirror) {
|
|
12 "use strict";
|
|
13
|
|
14 var keywords = ("this super static final const abstract class extends external factory " +
|
|
15 "implements mixin get native set typedef with enum throw rethrow assert break case " +
|
|
16 "continue default in return new deferred async await covariant try catch finally " +
|
|
17 "do else for if switch while import library export part of show hide is as extension " +
|
|
18 "on yield late required sealed base interface when").split(" ");
|
|
19 var blockKeywords = "try catch finally do else for if switch while".split(" ");
|
|
20 var atoms = "true false null".split(" ");
|
|
21 var builtins = "void bool num int double dynamic var String Null Never".split(" ");
|
|
22
|
|
23 function set(words) {
|
|
24 var obj = {};
|
|
25 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
|
26 return obj;
|
|
27 }
|
|
28
|
|
29 function pushInterpolationStack(state) {
|
|
30 (state.interpolationStack || (state.interpolationStack = [])).push(state.tokenize);
|
|
31 }
|
|
32
|
|
33 function popInterpolationStack(state) {
|
|
34 return (state.interpolationStack || (state.interpolationStack = [])).pop();
|
|
35 }
|
|
36
|
|
37 function sizeInterpolationStack(state) {
|
|
38 return state.interpolationStack ? state.interpolationStack.length : 0;
|
|
39 }
|
|
40
|
|
41 CodeMirror.defineMIME("application/dart", {
|
|
42 name: "clike",
|
|
43 keywords: set(keywords),
|
|
44 blockKeywords: set(blockKeywords),
|
|
45 builtin: set(builtins),
|
|
46 atoms: set(atoms),
|
|
47 // clike numbers without the suffixes, and with '_' separators.
|
|
48 number: /^(?:0x[a-f\d_]+|(?:[\d_]+\.?[\d_]*|\.[\d_]+)(?:e[-+]?[\d_]+)?)/i,
|
|
49 hooks: {
|
|
50 "@": function(stream) {
|
|
51 stream.eatWhile(/[\w\$_\.]/);
|
|
52 return "meta";
|
|
53 },
|
|
54
|
|
55 // custom string handling to deal with triple-quoted strings and string interpolation
|
|
56 "'": function(stream, state) {
|
|
57 return tokenString("'", stream, state, false);
|
|
58 },
|
|
59 "\"": function(stream, state) {
|
|
60 return tokenString("\"", stream, state, false);
|
|
61 },
|
|
62 "r": function(stream, state) {
|
|
63 var peek = stream.peek();
|
|
64 if (peek == "'" || peek == "\"") {
|
|
65 return tokenString(stream.next(), stream, state, true);
|
|
66 }
|
|
67 return false;
|
|
68 },
|
|
69
|
|
70 "}": function(_stream, state) {
|
|
71 // "}" is end of interpolation, if interpolation stack is non-empty
|
|
72 if (sizeInterpolationStack(state) > 0) {
|
|
73 state.tokenize = popInterpolationStack(state);
|
|
74 return null;
|
|
75 }
|
|
76 return false;
|
|
77 },
|
|
78
|
|
79 "/": function(stream, state) {
|
|
80 if (!stream.eat("*")) return false
|
|
81 state.tokenize = tokenNestedComment(1)
|
|
82 return state.tokenize(stream, state)
|
|
83 },
|
|
84 token: function(stream, _, style) {
|
|
85 if (style == "variable") {
|
|
86 // Assume uppercase symbols are classes using variable-2
|
|
87 var isUpper = RegExp('^[_$]*[A-Z][a-zA-Z0-9_$]*$','g');
|
|
88 if (isUpper.test(stream.current())) {
|
|
89 return 'variable-2';
|
|
90 }
|
|
91 }
|
|
92 }
|
|
93 }
|
|
94 });
|
|
95
|
|
96 function tokenString(quote, stream, state, raw) {
|
|
97 var tripleQuoted = false;
|
|
98 if (stream.eat(quote)) {
|
|
99 if (stream.eat(quote)) tripleQuoted = true;
|
|
100 else return "string"; //empty string
|
|
101 }
|
|
102 function tokenStringHelper(stream, state) {
|
|
103 var escaped = false;
|
|
104 while (!stream.eol()) {
|
|
105 if (!raw && !escaped && stream.peek() == "$") {
|
|
106 pushInterpolationStack(state);
|
|
107 state.tokenize = tokenInterpolation;
|
|
108 return "string";
|
|
109 }
|
|
110 var next = stream.next();
|
|
111 if (next == quote && !escaped && (!tripleQuoted || stream.match(quote + quote))) {
|
|
112 state.tokenize = null;
|
|
113 break;
|
|
114 }
|
|
115 escaped = !raw && !escaped && next == "\\";
|
|
116 }
|
|
117 return "string";
|
|
118 }
|
|
119 state.tokenize = tokenStringHelper;
|
|
120 return tokenStringHelper(stream, state);
|
|
121 }
|
|
122
|
|
123 function tokenInterpolation(stream, state) {
|
|
124 stream.eat("$");
|
|
125 if (stream.eat("{")) {
|
|
126 // let clike handle the content of ${...},
|
|
127 // we take over again when "}" appears (see hooks).
|
|
128 state.tokenize = null;
|
|
129 } else {
|
|
130 state.tokenize = tokenInterpolationIdentifier;
|
|
131 }
|
|
132 return null;
|
|
133 }
|
|
134
|
|
135 function tokenInterpolationIdentifier(stream, state) {
|
|
136 stream.eatWhile(/[\w_]/);
|
|
137 state.tokenize = popInterpolationStack(state);
|
|
138 return "variable";
|
|
139 }
|
|
140
|
|
141 function tokenNestedComment(depth) {
|
|
142 return function (stream, state) {
|
|
143 var ch
|
|
144 while (ch = stream.next()) {
|
|
145 if (ch == "*" && stream.eat("/")) {
|
|
146 if (depth == 1) {
|
|
147 state.tokenize = null
|
|
148 break
|
|
149 } else {
|
|
150 state.tokenize = tokenNestedComment(depth - 1)
|
|
151 return state.tokenize(stream, state)
|
|
152 }
|
|
153 } else if (ch == "/" && stream.eat("*")) {
|
|
154 state.tokenize = tokenNestedComment(depth + 1)
|
|
155 return state.tokenize(stream, state)
|
|
156 }
|
|
157 }
|
|
158 return "comment"
|
|
159 }
|
|
160 }
|
|
161
|
|
162 CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins));
|
|
163
|
|
164 // This is needed to make loading through meta.js work.
|
|
165 CodeMirror.defineMode("dart", function(conf) {
|
|
166 return CodeMirror.getMode(conf, "application/dart");
|
|
167 }, "clike");
|
|
168 });
|