From b107d558afacc4304120e5f83201c5eda70c89cc Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Wed, 30 Aug 2023 17:55:43 +0200 Subject: [PATCH] Update codemirror. --- src/assets/codemirror/toit.js | 238 ++++++++++++++++++++++++---------- 1 file changed, 171 insertions(+), 67 deletions(-) diff --git a/src/assets/codemirror/toit.js b/src/assets/codemirror/toit.js index b257bc66..bb4daaff 100644 --- a/src/assets/codemirror/toit.js +++ b/src/assets/codemirror/toit.js @@ -1,9 +1,13 @@ /* eslint-disable */ -// Code copied from toitware/toit. DO NOT EDIT. -// CodeMirror, copyright (c) by Toitware ApS. -// Distributed under an MIT license: https://codemirror.net/LICENSE +// Code copied from toitware/ide-tools. DO NOT EDIT. + +// Copyright (C) 2021 Toitware ApS. All rights reserved. +// Use of this source code is governed by an MIT-style license that can be +// found in the LICENSE file. (function (mod) { + if (typeof CodeMirror !== "undefined") // Just use the variable if it already exits. + mod(CodeMirror); if (typeof window === "undefined" || typeof window.navigator == 'undefined') import("codemirror").then(mod); else if ( typeof module == "object" && module.hot) @@ -16,6 +20,7 @@ mod(CodeMirror); })(function (CodeMirror) { "use strict"; + CodeMirror.defineMode("toit", function (config) { function last(array) { return array[array.length - 1]; @@ -23,28 +28,34 @@ function set_last(array, val) { array[array.length - 1] = val; } + function subState(state) { return last(state.subState); } function setSubState(state, subState) { state.subState[state.subState.length - 1] = subState; } + function makeJsObject(str) { var result = {}; var split = str.split("|"); for (var i = 0; i < split.length; i++) result[split[i]] = true; return result; } - var keywords = makeJsObject("assert|and|or|not|if|for|else|try|finally|" + + var keywords = makeJsObject( + "assert|and|or|not|if|for|else|try|finally|" + "while|break|continue|throw|static|abstract|return|unreachable"); var atoms = makeJsObject("true|false|null"); var specialVars = makeJsObject("this|super|it"); - var IDENTIFIER = /[a-zA-Z_]\w*/; - var TYPE = /[a-zA-Z_]\w*(\.[a-zA-Z_]\w*)?/; - var OVERRIDABLE_OPERATOR = /==|>=|<=|<<|>>>|>>|\*|\+|-|%|\/|<|>|&|\||\^|~|\[\]\=|\[\]|\[\.\.\]/; - var CONSTANT_HEURISTIC = /_?[A-Z][A-Z_0-9]+/; - var TYPE_HEURISTIC = /_?[A-Z]\w*[a-z]\w*/; + + var IDENTIFIER = /[a-zA-Z_]([\w-]*\w)?/; + var TYPE = /[a-zA-Z_]([\w-]*\w)?(\.[a-zA-Z_]([\w-]*\w)?)?/; + var OVERRIDABLE_OPERATOR = /==|>=|<=|<<|>>>|>>|\*|\+|-|%|\/|<|>|&|\||\^|~|\[\]\=|\[\]|\[\.\.\]/ + + var CONSTANT_HEURISTIC = /^_?[A-Z][A-Z_0-9-]*$/; + var TYPE_HEURISTIC = /^_?[A-Z][\w-]*[a-z][\w-]*$/; var CONTROL = /[?:;]/; + function isKeyword(str) { return keywords.propertyIsEnumerable(str); } @@ -57,6 +68,7 @@ function isReserved(str) { return isKeyword(str) || isAtom(str) || isSpecialVar(str); } + function tryComments(stream, state) { // TODO: once code-mirror supports doc-comments, adjust. if (stream.match("//")) { @@ -68,11 +80,13 @@ } return null; } + function tokenizeMultilineComment(stream, state) { state.context.push([tokenizeMultilineCommentEnd, -1]); state.subState.push(null); return tokenizeMultilineCommentEnd(stream, state); } + function tokenizeMultilineCommentEnd(stream, state) { while (true) { if (stream.match("/*")) { @@ -89,6 +103,7 @@ } } } + var STRING_PART = 0; var STRING_ESCAPE_DOLLAR = 1; var STRING_ESCAPE_EXPRESSION = 2; @@ -109,6 +124,7 @@ } return null; } + function tokenizeDelimited(stream, state) { var closing = subState(state); var expression_result = tryExpression(stream, state); @@ -130,16 +146,15 @@ case "]": return "bracket"; } return "error"; - } - else if (next == ',') { + } else if (next == ',') { if (closing == ")") return "error"; return "separator"; - } - else { + } else { return "error"; } } } + function tryDelimited(stream, state) { if (stream.match(/[({[]|#[[]/)) { state.context.push([tokenizeDelimited, -1]); @@ -156,11 +171,13 @@ return style; } } + function tryControl(stream, state) { if (stream.match(CONTROL)) { return "control"; } } + function tokenizeIs(stream, state) { state.context.pop(); state.subState.pop(); @@ -168,11 +185,11 @@ state.subState.push(null); if (stream.match(/not\b/)) { return "is_as"; - } - else { - tokenizeIsAs(stream, state); + } else { + tokenizeIsAs(stream, state) } } + function tokenizeIsAs(stream, state) { state.context.pop(); state.subState.pop(); @@ -181,6 +198,7 @@ } return tokenizeType(stream, state); } + function tryIsAs(stream, state) { if (stream.match(/is\b/)) { state.context.push([tokenizeIs, -1]); @@ -193,6 +211,7 @@ return "is_as"; } } + function tokenizeEscape(stream, state) { switch (subState(state)) { case STRING_ESCAPE_DOLLAR: @@ -204,6 +223,7 @@ } setSubState(state, STRING_ESCAPE_EXPRESSION); return "string_dollar"; + case STRING_ESCAPE_EXPRESSION: if (stream.match('(')) { setSubState(state, STRING_ESCAPE_AFTER_PAREN); @@ -218,6 +238,7 @@ } setSubState(state, STRING_ESCAPE_AFTER_IDENTIFIER); return identifier_result; + case STRING_ESCAPE_AFTER_IDENTIFIER: if (stream.match(/\.[a-zA-Z_]/, false)) { stream.next(); @@ -237,6 +258,7 @@ } setSubState(state, STRING_PART); return null; + case STRING_ESCAPE_AFTER_PAREN: if (stream.peek() == '%') { stream.eatWhile(/[^ ]/); @@ -250,10 +272,12 @@ // Abusing `subState` to store the delimiter. state.subState.push(")"); return tokenizeDelimited(stream, state); + default: throw "INTERNAL ERROR"; } } + function tokenizeSinglelineString(stream, state) { if (subState(state) != STRING_PART) { var escape_result = tokenizeEscape(stream, state); @@ -278,6 +302,7 @@ return "singleline_string"; } } + function tokenizeMultilineString(stream, state) { if (subState(state) != STRING_PART) { var escape_result = tokenizeEscape(stream, state); @@ -301,6 +326,7 @@ } } } + function tryChar(stream, state) { if (stream.match("'")) { while (true) { @@ -316,6 +342,7 @@ } return null; } + function tryNumber(stream, state) { if (stream.match(/(\d(\d|_\d)*)?\.\d(\d|_\d)*([eE][+-]?\d(\d|_\d)*)?/)) return "float"; // 0.5e10 and .5e+10 if (stream.match(/\d(\d|_\d)*[eE][+-]?\d(\d|_\d)*/)) return "float"; // 1e+10 @@ -326,6 +353,7 @@ if (stream.match(/\d(\d|_\d)*/)) return "integer"; return null; } + function tryNamedArgument(stream, state) { if (stream.match("--")) { if (stream.match(IDENTIFIER)) return "named_argument"; @@ -333,37 +361,39 @@ } return null; } + function tryOperator(stream, state) { if (stream.match(/\*|\+|-|%|\/|<<|>>>|>>|&|\||\^|~/)) { if (stream.match("=")) { return "op_assig"; } - return "overridable_op"; + return "overridable_op" } if (stream.match(/==|!=|>=|<=|<|>/)) { return "relational"; } if (stream.match("=")) { - return "assig"; + return "assig" } if (stream.match(/:=|::=/)) { return "define"; } return null; } + var LOCAL_ANNOTATION_DIV = 0; var LOCAL_ANNOTATION_TYPE = 1; function localAnnotation(stream, state) { var sub = subState(state); if (sub == LOCAL_ANNOTATION_DIV) { if (stream.match("/")) { - setSubState(state, LOCAL_ANNOTATION_TYPE); + setSubState(state, LOCAL_ANNOTATION_TYPE) return "type_div"; } - throw "Internal Error"; + throw "Internal Error" } if (sub != LOCAL_ANNOTATION_TYPE) { - throw "Internal Error"; + throw "Internal Error" } state.context.pop(); state.subState.pop(); @@ -372,21 +402,30 @@ } return null; } - function tryIdentifier(stream, state) { + + function tryPostfixMemberOrIdentifier(stream, state) { + return tryIdentifier(stream, state, true); + } + + function tryIdentifier(stream, state, allowPrefixedDot) { + // If we allow a prefixed dot, consume it (but put it back if + // it's not followed by an identifier). + if (allowPrefixedDot && stream.match(".")) { + if (!stream.match(IDENTIFIER, false)) { + stream.backUp(1); + return null; + } + return "dot"; + } if (!stream.match(IDENTIFIER)) return null; var id = stream.current(); if (isKeyword(id)) return "keyword"; if (isSpecialVar(id)) return "special_var"; if (isAtom(id)) return "atom"; - if (id.match(CONSTANT_HEURISTIC)) { - return "constant"; - } - if (id.match(TYPE_HEURISTIC)) { - return "type"; - } - if (stream.match(/[ ]*:?:=/, false)) { - return "declaration"; - } + if (id.match(CONSTANT_HEURISTIC)) return "constant"; + if (id.match(TYPE_HEURISTIC)) return "type"; + if (stream.match(/[ ]*:?:=/, false)) return "declaration"; + if (stream.match(/[ ]*[/][ ]*[\w_.]+[?]?[ ]*:?:=/, false)) { state.context.push([localAnnotation, -1]); state.subState.push(LOCAL_ANNOTATION_DIV); @@ -394,12 +433,14 @@ } return "identifier"; } + function tryPrimitive(stream, state) { if (stream.match(/#primitive\b/)) { return "primitive"; } return null; } + var TYPE_START = 0; var TYPE_START_NULLABLE = 1; var TYPE_AFTER_PREFIX = 2; @@ -420,6 +461,7 @@ state.subState.push(allowNullable ? TYPE_START_NULLABLE : TYPE_START); return tokenizeType2(stream, state); } + function tokenizeType2(stream, state) { var sub = subState(state); if (sub == TYPE_START || sub == TYPE_START_NULLABLE) { @@ -443,6 +485,7 @@ if (sub == TYPE_AFTER_PREFIX_NULLABLE) stream.match("?"); return "type_name"; } + var IMPORT_AFTER_IMPORT = 0; var IMPORT_AFTER_PATH = 1; var IMPORT_AFTER_SHOW = 2; @@ -452,18 +495,20 @@ if (stream.match(/import\b/)) { state.context.push([tokenizeImport, 2]); state.subState.push(IMPORT_AFTER_IMPORT); - return "keyword"; + return "keyword" } return null; } function tokenizeImport(stream, state) { var comment_result = tryComments(stream, state); if (comment_result) return comment_result; + function importError() { setSubState(state, IMPORT_ERROR); stream.skipToEnd(); return "error"; } + switch (subState(state)) { case IMPORT_AFTER_IMPORT: if (!stream.match(/\.*(\.?[a-zA-Z_]\w*)+/)) return importError(); @@ -497,19 +542,21 @@ return "import_error"; } } + var EXPORT_AFTER_EXPORT = 0; var EXPORT_ERROR = 1; function tryExport(stream, state) { if (stream.match(/export\b/)) { state.context.push([tokenizeExport, 2]); state.subState.push(EXPORT_AFTER_EXPORT); - return "keyword"; + return "keyword" } return null; } function tokenizeExport(stream, state) { var comment_result = tryComments(stream, state); if (comment_result) return comment_result; + switch (subState(state)) { case EXPORT_AFTER_EXPORT: if (stream.match("*")) { @@ -527,10 +574,11 @@ return "export_error"; } } + var CLASS_SIGNATURE_AFTER_CLASS = 0; var CLASS_SIGNATURE_AFTER_NAME = 1; var CLASS_SIGNATURE_AFTER_EXTENDS = 2; - var CLASS_SIGNATURE_AFTER_EXTENDS_TYPE = 3; + var CLASS_SIGNATURE_AFTER_EXTENDS_TYPE = 3 var CLASS_SIGNATURE_AFTER_IMPLEMENTS = 4; var CLASS_SIGNATURE_AFTER_FIRST_IMPLEMENTS_NAME = 5; var CLASS_BODY = 6; @@ -538,36 +586,42 @@ if (stream.match(/(abstract[ ]+)?class\b/) || stream.match(/interface\b/)) { state.context.push([tokenizeClass, 2]); state.subState.push(CLASS_SIGNATURE_AFTER_CLASS); - return "keyword"; + return "keyword" } return null; } + function tokenizeClassError(stream, state) { // This function will be popped by indentation. stream.skipToEnd(); return "class_error"; } + function tokenizeClass(stream, state) { var comment_result = tryComments(stream, state); if (comment_result) return comment_result; + function signatureError() { - setSubState(state, CLASS_BODY); // Once the error function is popped. + setSubState(state, CLASS_BODY); // Once the error function is popped. // Eat everything until we are back to 2-indentation. state.context.push([tokenizeClassError, 4]); - state.subState.push(null); + state.subState.push(null) return tokenizeClassError(stream, state); } + switch (subState(state)) { case CLASS_SIGNATURE_AFTER_CLASS: if (!stream.match(IDENTIFIER)) return signatureError(); setSubState(state, CLASS_SIGNATURE_AFTER_NAME); return "class_name"; + case CLASS_SIGNATURE_AFTER_NAME: if (stream.match(/extends\b/)) { setSubState(state, CLASS_SIGNATURE_AFTER_EXTENDS); return "keyword"; } // Fall through. + case CLASS_SIGNATURE_AFTER_EXTENDS_TYPE: if (stream.match(/implements\b/)) { setSubState(state, CLASS_SIGNATURE_AFTER_IMPLEMENTS); @@ -578,15 +632,18 @@ return "class_body_colon"; } return signatureError(); + case CLASS_SIGNATURE_AFTER_EXTENDS: if (!stream.match(TYPE, false)) return signatureError(); setSubState(state, CLASS_SIGNATURE_AFTER_EXTENDS_TYPE); return tokenizeType(stream, state, false); + case CLASS_SIGNATURE_AFTER_IMPLEMENTS: // The first *requires* an type. if (!stream.match(TYPE, false)) return signatureError(); setSubState(state, CLASS_SIGNATURE_AFTER_FIRST_IMPLEMENTS_NAME); return tokenizeType(stream, state, false); + case CLASS_SIGNATURE_AFTER_FIRST_IMPLEMENTS_NAME: if (stream.match(TYPE, false)) { return tokenizeType(stream, state, false); @@ -596,15 +653,18 @@ return "class_body_colon"; } return signatureError(); + case CLASS_BODY: state.context.push([tokenizeMemberDeclaration, 4]); state.subState.push(MEMBER_DECLARATION_START); return tokenizeMemberDeclaration(stream, state); + default: stream.skipToEnd(); return "unformatted"; } } + var MEMBER_DECLARATION_START = 0; var MEMBER_DECLARATION_AFTER_STATIC_ABSTRACT = 1; var MEMBER_DECLARATION_AFTER_OPERATOR = 2; @@ -612,6 +672,7 @@ function tokenizeMemberDeclaration(stream, state) { var comment_result = tryComments(stream, state); if (comment_result) return comment_result; + if (subState(state) == MEMBER_DECLARATION_START) { if (stream.match(/abstract\b/) || stream.match(/static\b/)) { setSubState(state, MEMBER_DECLARATION_AFTER_STATIC_ABSTRACT); @@ -624,25 +685,25 @@ if (stream.match(/constructor\b/)) { if (stream.match(/\.[a-zA-Z_]\w*/, false)) { setSubState(state, MEMBER_DECLARATION_AFTER_NAMED_CONSTRUCTOR); - } - else { + } else { state.context.push([tokenizeFunctionBody, 4]); state.subState.push(null); state.context.push([tokenizeFunctionSignature, 6]); state.subState.push(null); } - return "constructor_keyword"; + return "constructor_keyword" } - } - else if (subState(state) == MEMBER_DECLARATION_AFTER_NAMED_CONSTRUCTOR) { + } else if (subState(state) == MEMBER_DECLARATION_AFTER_NAMED_CONSTRUCTOR) { stream.match(/\.[a-zA-Z_]\w*/); state.context.push([tokenizeFunctionBody, 4]); state.subState.push(null); state.context.push([tokenizeFunctionSignature, 6]); state.subState.push(null); - return "member_named_constructor"; + return "member_named_constructor" } + var currentSubState = subState(state); + // Even if things go wrong, assume that we are going to parse the rest of // the signature first, followed by the body. // If we find a `:` we will pop the signature by hand. @@ -651,9 +712,8 @@ state.context.push([tokenizeFunctionSignature, 6]); state.subState.push(null); if (currentSubState == MEMBER_DECLARATION_AFTER_OPERATOR && stream.match(OVERRIDABLE_OPERATOR)) { - return "member_operator_name"; - } - else if (stream.match(IDENTIFIER)) { + return "member_operator_name" + } else if (stream.match(IDENTIFIER)) { if (isReserved(stream.current())) { return "member_name_error"; } @@ -665,23 +725,24 @@ return "named_constructor"; } return "member_name_error"; - } - else if (stream.match("=")) { + } else if (stream.match("=")) { return "member_name_setter"; - } - else { + } else { return "member_name"; } } - stream.eatWhile(/[^ ]/); // Skip to the next whitespace. + stream.eatWhile(/[^ ]/); // Skip to the next whitespace. return "member_name_error"; } + function tokenizeFunctionBody(stream, state) { var matched_result = tryExpression(stream, state); if (matched_result) return matched_result; + stream.eatWhile(/[^ ]/); return "unformatted"; } + function tryDefaultValue(stream, state) { var expression_result = tryNumber(stream, state) || tryString(stream, state) || @@ -697,6 +758,7 @@ } return null; } + var DEFAULT_VALUE_AFTER_IDENTIFIER = 0; var DEFAULT_VALUE_AFTER_DOT = 1; function tokenizeDefaultValueContinuation(stream, state) { @@ -719,23 +781,27 @@ state.context.pop(); state.subState.pop(); return last(state.context)[0](stream, state); + case DEFAULT_VALUE_AFTER_DOT: setSubState(state, DEFAULT_VALUE_AFTER_IDENTIFIER); return tryIdentifier(stream, state); } } + var SIGNATURE_EXPECTING_DEFAULT_VALUE = 0; var SIGNATURE_EXPECTING_TYPE = 1; var SIGNATURE_AFTER_BRACKET_BLOCK = 2; function tokenizeFunctionSignature(stream, state) { var comment_result = tryComments(stream, state); if (comment_result) return comment_result; + function error(kind) { if (!result) { - stream.eatWhile(/[^ ]/); // Skip to the next whitespace. + stream.eatWhile(/[^ ]/); // Skip to the next whitespace. result = kind || "parameter_error"; } } + if (stream.match("::=") || stream.match(":=")) { state.context.pop(); state.subState.pop(); @@ -746,6 +812,7 @@ state.subState.pop(); return "function_colon"; } + switch (subState(state)) { case SIGNATURE_EXPECTING_DEFAULT_VALUE: setSubState(state, null); // For when the sub-expression returns. @@ -757,6 +824,7 @@ setSubState(state, null); if (!stream.match(TYPE, false)) return error(); return tokenizeType(stream, state, true); + default: // Continue after the `switch`. } @@ -770,7 +838,7 @@ } if (stream.match("=")) { setSubState(state, SIGNATURE_EXPECTING_DEFAULT_VALUE); - return "default_equals"; + return "default_equals" } if (stream.match("[")) { setSubState(state, SIGNATURE_AFTER_BRACKET_BLOCK); @@ -805,11 +873,11 @@ } if (isNamed) { return "named_parameter"; - } - else { + } else { return "parameter"; } } + function tryToplevelDeclaration(stream, state) { if (stream.match(IDENTIFIER)) { state.context.push([tokenizeFunctionBody, 2]); @@ -829,19 +897,27 @@ } return null; } - // If all else fails, we assume that we are implicitly inside a function + + // For code snippets that have an indent on the very first + // line we assume that we are implicitly inside a function // like "main". function tryImpliedTopLevelFunction(stream, state) { - state.context.push([tokenizeFunctionBody, 0]); - state.subState.push(null); - return "null"; + if (state.startOfLine && stream.indentation() == 2) { + state.context.push([tokenizeFunctionBody, 2]); + state.subState.push(null); + return "null"; + } + return null; } + + function tokenizeError(stream, state) { // We could try to be more aggressive (like trying to highlight numbers, // strings, ...), but the most important thing is that we make progress. stream.skipToEnd(); return "error"; } + function tryExpression(stream, state) { return tryComments(stream, state) || tryNumber(stream, state) || @@ -850,20 +926,26 @@ tryOperator(stream, state) || tryString(stream, state) || tryIsAs(stream, state) || + // In theory we need to check whether the postfix member is + // prefixed by another expression but for the syntax highlighter we + // just assume that was the case. + tryPostfixMemberOrIdentifier(stream, state) || tryIdentifier(stream, state) || tryPrimitive(stream, state) || tryDelimited(stream, state) || tryControl(stream, state); } + function tokenizeTopLevel(stream, state) { return tryComments(stream, state) || tryImport(stream, state) || tryExport(stream, state) || tryClass(stream, state) || - tryToplevelDeclaration(stream, state) || tryImpliedTopLevelFunction(stream, state) || + tryToplevelDeclaration(stream, state) || tokenizeError(stream, state); } + return { startState: function (basecolumn) { return { @@ -877,23 +959,23 @@ subState: [null] }; }, + token: function (stream, state) { if (stream.sol()) { state.startOfLine = true; state.readNonWhitespace = false; - } - else if (state.readNonWhitespace) { + } else if (state.readNonWhitespace) { state.startOfLine = false; } if (stream.eatSpace()) return null; if (stream.peek() == ":") { state.atColonIndentation = stream.indentation(); - } - else { + } else { state.atColonIndentation = -1; } // Next time we aren't at the beginning of the line anymore. state.readNonWhitespace = true; + if (state.startOfLine) { // Drop contexts if there is a dedent. while (last(state.context)[1] > stream.indentation()) { @@ -901,12 +983,14 @@ state.subState.pop(); } } + var tokenizer = last(state.context)[0]; var result = tokenizer(stream, state); if (!result) return result; // We have a more nuanced parsing, allowing for better highlighting // (once that's supported, or if there is a better style). // Simplify here, so that the standard CSS works. + // CodeMirror highlighting styles: // - meta // - keyword @@ -926,12 +1010,14 @@ // - attribute // - link // - error + switch (result) { case "unformatted": case "import_path": case "export_identifier": result = null; break; + case "type_special": case "keyword": case "is_as": @@ -939,11 +1025,13 @@ case "control": result = "keyword"; break; + case "atom": case "constant": case "toplevel_constant": result = "atom"; break; + case "float": case "hex_float": case "integer": @@ -951,6 +1039,7 @@ case "binary": result = "number"; break; + case "member_name": case "member_name_setter": case "member_named_constructor": @@ -959,28 +1048,32 @@ case "toplevel_name_setter": case "class_name": case "member_operator_name": - result = "def"; + result = "def"; break; + case "import_show_identifier": case "named_constructor": case "named_parameter": case "parameter": result = "variable"; break; + case "identifier": result = "variable-2"; break; + case "type": case "type_name": case "type_short": result = "type"; break; + case "import_star": case "export_star": case "type_dot": case "default_equals": case "function_colon": - case "field_assig": // Also for globals. + case "field_assig": // Also for globals. case "type_div": case "type_return": case "class_body_colon": @@ -996,32 +1089,38 @@ case "separator": result = "operator"; break; + case "singleline_string": case "multiline_string": case "character": result = "string"; break; + case "unfinished_string": case "missing_escape_expression": case "unfinished_character": result = "string error"; break; + case "string_format": case "named_argument": case "import_prefix_name": case "type_prefix": result = "qualifier"; break; + case "special_var": case "primitive": result = "builtin"; break; + case "bracket_block_open": case "bracket_block_close": case "paren": case "bracket": result = "bracket"; break; + case "import_error": case "export_error": case "class_error": @@ -1031,19 +1130,22 @@ case "toplevel_name_error": case "default_value_dot_error": case "is_as_error": - result = "error"; // Might want to just not color. + result = "error"; // Might want to just not color. break; + default: /* do nothing. */ break; } return result; }, + indent: function (state, textAfter) { if (state.atColonIndentation == -1) return CodeMirror.Pass; // We don't use `config.indentUnit`. Toit is 2 chars. return state.atColonIndentation + 2; }, + closeBrackets: { triples: "\"" }, lineComment: "//", blockCommentStart: "/*", @@ -1051,5 +1153,7 @@ fold: "indent", }; }); + CodeMirror.defineMIME("text/x-toit", "toit"); + });