Created
February 5, 2022 12:32
-
-
Save Ruminat/42364312e90ba5d71875697ede66990e to your computer and use it in GitHub Desktop.
A Groovy language for monaco editor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { languages } from "monaco-editor"; | |
function getTokens(tokens: string, divider = "|"): string[] { | |
return tokens.split(divider); | |
} | |
const wordPattern = /(-?\d*\.\d\w*)|([^`~!@#%^&*()\-=+[{\]}\\|;:'",./?\s]+)/g; | |
const brackets: languages.CharacterPair[] = [ | |
["{", "}"], | |
["[", "]"], | |
["(", ")"], | |
]; | |
const bracketTokens = [ | |
{ | |
open: "[", | |
close: "]", | |
token: "delimiter.square", | |
}, | |
{ | |
open: "(", | |
close: ")", | |
token: "delimiter.parenthesis", | |
}, | |
{ | |
open: "{", | |
close: "}", | |
token: "delimiter.curly", | |
}, | |
]; | |
const autoClosingPairs = [ | |
{ open: "{", close: "}" }, | |
{ open: "[", close: "]" }, | |
{ open: "(", close: ")" }, | |
{ open: '"', close: '"' }, | |
{ open: "'", close: "'" }, | |
{ open: "`", close: "`" }, | |
]; | |
const surroundingPairs = autoClosingPairs; | |
const id = "groovy"; | |
const label = "Groovy"; | |
export const registerGroovyLanguageForMonaco = () => { | |
languages.register({ id, aliases: [label] }); | |
languages.setMonarchTokensProvider(id, { | |
brackets: bracketTokens, | |
tokenPostfix: ".groovy", | |
keywords: getTokens( | |
"assert|with|abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|def|float|native|super|while|in|as" | |
), | |
typeKeywords: getTokens( | |
"Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object" | |
), | |
constants: getTokens("null|Infinity|NaN|undefined|true|false"), | |
builtinFunctions: getTokens( | |
"AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException" | |
), | |
operators: [ | |
".", | |
".&", | |
".@", | |
"?.", | |
"*", | |
"*.", | |
"*:", | |
"~", | |
"!", | |
"++", | |
"--", | |
"**", | |
"+", | |
"-", | |
"*", | |
"/", | |
"%", | |
"<<", | |
">>", | |
">>>", | |
"..", | |
"..<", | |
"<", | |
"<=", | |
">", | |
">", | |
"==", | |
"!=", | |
"<=>", | |
"===", | |
"!==", | |
"=~", | |
"==~", | |
"^", | |
"|", | |
"&&", | |
"||", | |
"?", | |
":", | |
"?:", | |
"=", | |
"**=", | |
"*=", | |
"/=", | |
"%=", | |
"+=", | |
"-=", | |
"<<=", | |
">>=", | |
">>>=", | |
"&=", | |
"^=", | |
"|=", | |
"?=", | |
], | |
symbols: /[=><!~?:&|+\-*/^%]+/, | |
escapes: /\\(?:[abfnrtv\\"'`]|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, | |
regexpctl: /[(){}[\]$^|\-*+?.]/, | |
regexpesc: /\\(?:[bBdDfnrstvwWn0\\/]|@regexpctl|c[A-Z]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/, | |
tokenizer: { | |
root: [ | |
{ include: "@whitespace" }, | |
[ | |
/\/(?=([^\\/]|\\.)+\/([dgimsuy]*)(\s*)(\.|;|,|\)|\]|\}|$))/, | |
{ token: "regexp", bracket: "@open", next: "@regexp" }, | |
], | |
{ include: "@comments" }, | |
{ include: "@numbers" }, | |
{ include: "common" }, | |
[/[;,.]/, "delimiter"], | |
[/[(){}[\]]/, "@brackets"], | |
[ | |
/[a-zA-Z_$]\w*/, | |
{ | |
cases: { | |
"@keywords": "keyword", | |
"@typeKeywords": "type", | |
"@constants": "constant.groovy", | |
"@builtinFunctions": "constant.other.color", | |
"@default": "identifier", | |
}, | |
}, | |
], | |
[ | |
/@symbols/, | |
{ | |
cases: { | |
"@operators": "operator", | |
"@default": "", | |
}, | |
}, | |
], | |
], | |
common: [ | |
// delimiters and operators | |
[/[()[\]]/, "@brackets"], | |
[/[<>](?!@symbols)/, "@brackets"], | |
[ | |
/@symbols/, | |
{ | |
cases: { | |
"@operators": "delimiter", | |
"@default": "", | |
}, | |
}, | |
], | |
[ | |
/\/(?=([^\\/]|\\.)+\/([gimsuy]*)(\s*)(\.|;|\/|,|\)|\]|\}|$))/, | |
{ token: "regexp", bracket: "@open", next: "@regexp" }, | |
], | |
// delimiter: after number because of .\d floats | |
[/[;,.]/, "delimiter"], | |
// strings | |
[/"([^"\\]|\\.)*$/, "string.invalid"], | |
[/'([^'\\]|\\.)*$/, "string.invalid"], | |
[/"/, "string", "@string_double"], | |
[/'/, "string", "@string_single"], | |
], | |
whitespace: [[/\s+/, "white"]], | |
comments: [ | |
[/\/\/.*/, "comment"], | |
[ | |
/\/\*/, | |
{ | |
token: "comment.quote", | |
next: "@comment", | |
}, | |
], | |
], | |
comment: [ | |
[/[^*/]+/, "comment"], | |
[ | |
/\*\//, | |
{ | |
token: "comment.quote", | |
next: "@pop", | |
}, | |
], | |
[/./, "comment"], | |
], | |
commentAnsi: [ | |
[ | |
/\/\*/, | |
{ | |
token: "comment.quote", | |
next: "@comment", | |
}, | |
], | |
[/[^*/]+/, "comment"], | |
[ | |
/\*\//, | |
{ | |
token: "comment.quote", | |
next: "@pop", | |
}, | |
], | |
[/./, "comment"], | |
], | |
numbers: [ | |
[/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?f?\b/, "number.float"], | |
[/[+-]?(?:0[obx])?\d+(?:u?[lst]?)?\b/, "number"], | |
], | |
regexp: [ | |
[/(\{)(\d+(?:,\d*)?)(\})/, ["regexp.escape.control", "regexp.escape.control", "regexp.escape.control"]], | |
[ | |
/(\[)(\^?)(?=(?:[^\]\\/]|\\.)+)/, | |
// @ts-ignore | |
["regexp.escape.control", { token: "regexp.escape.control", next: "@regexrange" }], | |
], | |
[/(\()(\?:|\?=|\?!)/, ["regexp.escape.control", "regexp.escape.control"]], | |
[/[()]/, "regexp.escape.control"], | |
[/@regexpctl/, "regexp.escape.control"], | |
[/[^\\/]/, "regexp"], | |
[/@regexpesc/, "regexp.escape"], | |
[/\\\./, "regexp.invalid"], | |
// @ts-ignore | |
[/(\/)([gimsuy]*)/, [{ token: "regexp", bracket: "@close", next: "@pop" }, "keyword.other"]], | |
], | |
regexrange: [ | |
[/-/, "regexp.escape.control"], | |
[/\^/, "regexp.invalid"], | |
[/@regexpesc/, "regexp.escape"], | |
[/[^\]]/, "regexp"], | |
[/\]/, { token: "regexp.escape.control", next: "@pop", bracket: "@close" }], | |
], | |
embedded: [ | |
[ | |
/([^@]|^)([@]{4})*[@]{2}([@]([^@]|$)|[^@]|$)/, | |
{ | |
token: "@rematch", | |
next: "@pop", | |
nextEmbedded: "@pop", | |
}, | |
], | |
], | |
string_double: [ | |
[/\$\{/, { token: "delimiter.bracket", next: "@bracketCounting" }], | |
[/[^\\"$]+/, "string"], | |
[/[^\\"]+/, "string"], | |
[/@escapes/, "string.escape"], | |
[/\\./, "string.escape.invalid"], | |
[/"/, "string", "@pop"], | |
], | |
string_single: [ | |
[/[^\\']+/, "string"], | |
[/@escapes/, "string.escape"], | |
[/\\./, "string.escape.invalid"], | |
[/'/, "string", "@pop"], | |
], | |
string_backtick: [ | |
[/\$\{/, { token: "delimiter.bracket", next: "@bracketCounting" }], | |
[/[^\\"$]+/, "string"], | |
[/@escapes/, "string.escape"], | |
[/\\./, "string.escape.invalid"], | |
[/"/, "string", "@pop"], | |
], | |
bracketCounting: [ | |
[/\{/, "delimiter.bracket", "@bracketCounting"], | |
[/\}/, "delimiter.bracket", "@pop"], | |
{ include: "common" }, | |
], | |
}, | |
}); | |
languages.setLanguageConfiguration(id, { | |
comments: { | |
lineComment: "//", | |
blockComment: ["/*", "*/"], | |
}, | |
brackets, | |
autoClosingPairs, | |
surroundingPairs, | |
wordPattern, | |
}); | |
}; |
@GeniusP
You need to call the registerGroovyLanguageForMonaco
function from this file somewhere in your project, and "groovy"
should be available as one of the monaco languages
Note that this lacks support for single and double quote multi-line strings.
I was getting some error
and editor was not coloring correctly
instead of looking like this
So after comparing to java language definition
I located the issue to
after removal the above mentioned error no longer shows itself, but I don't realy understand what went wrong.
So here the edited file
import { languages } from "monaco-editor";
function getTokens(tokens: string, divider = "|"): string[] {
return tokens.split(divider);
}
const wordPattern = /(-?\d*\.\d\w*)|([^`~!@#%^&*()\-=+[{\]}\\|;:'",./?\s]+)/g;
const brackets: languages.CharacterPair[] = [
["{", "}"],
["[", "]"],
["(", ")"],
];
const autoClosingPairs = [
{ open: "{", close: "}" },
{ open: "[", close: "]" },
{ open: "(", close: ")" },
{ open: '"', close: '"' },
{ open: "'", close: "'" },
{ open: "`", close: "`" },
];
const surroundingPairs = autoClosingPairs;
const id = "groovy";
const label = "Groovy";
export const registerGroovyLanguageForMonaco = () => {
languages.register({ id, aliases: [label] });
languages.setMonarchTokensProvider(id, {
tokenPostfix: ".groovy",
keywords: getTokens(
"assert|with|abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|def|float|native|super|while|in|as"
),
typeKeywords: getTokens(
"Long|Integer|Short|Byte|Double|Number|Float|Character|Boolean|StackTraceElement|Appendable|StringBuffer|Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|StackOverflowError|OutOfMemoryError|VirtualMachineError|ArrayStoreException|ClassCastException|LinkageError|NoClassDefFoundError|ClassNotFoundException|RuntimeException|Exception|ThreadDeath|Error|Throwable|System|ClassLoader|Cloneable|Class|CharSequence|Comparable|String|Object"
),
constants: getTokens("null|Infinity|NaN|undefined|true|false"),
builtinFunctions: getTokens(
"AbstractMethodError|AssertionError|ClassCircularityError|ClassFormatError|Deprecated|EnumConstantNotPresentException|ExceptionInInitializerError|IllegalAccessError|IllegalThreadStateException|InstantiationError|InternalError|NegativeArraySizeException|NoSuchFieldError|Override|Process|ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|SuppressWarnings|TypeNotPresentException|UnknownError|UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|InstantiationException|IndexOutOfBoundsException|ArrayIndexOutOfBoundsException|CloneNotSupportedException|NoSuchFieldException|IllegalArgumentException|NumberFormatException|SecurityException|Void|InheritableThreadLocal|IllegalStateException|InterruptedException|NoSuchMethodException|IllegalAccessException|UnsupportedOperationException|Enum|StrictMath|Package|Compiler|Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|NullPointerException"
),
operators: [
".",
".&",
".@",
"?.",
"*",
"*.",
"*:",
"~",
"!",
"++",
"--",
"**",
"+",
"-",
"*",
"/",
"%",
"<<",
">>",
">>>",
"..",
"..<",
"<",
"<=",
">",
">=",
"==",
"!=",
"<=>",
"===",
"!==",
"=~",
"==~",
"^",
"|",
"&&",
"||",
"?",
":",
"?:",
"=",
"**=",
"*=",
"/=",
"%=",
"+=",
"-=",
"<<=",
">>=",
">>>=",
"&=",
"^=",
"|=",
"?=",
],
symbols: /[=><!~?:&|+\-*/^%]+/,
escapes: /\\(?:[abfnrtv\\"'`]|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
regexpctl: /[(){}[\]$^|\-*+?.]/,
regexpesc: /\\(?:[bBdDfnrstvwWn0\\/]|@regexpctl|c[A-Z]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/,
tokenizer: {
root: [
{ include: "@whitespace" },
[
/\/(?=([^\\/]|\\.)+\/([dgimsuy]*)(\s*)(\.|;|,|\)|\]|\}|$))/,
{ token: "regexp", bracket: "@open", next: "@regexp" },
],
{ include: "@comments" },
{ include: "@numbers" },
{ include: "common" },
[/[;,.]/, "delimiter"],
[/[(){}[\]]/, "@brackets"],
[
/[a-zA-Z_$]\w*/,
{
cases: {
"@keywords": "keyword",
"@typeKeywords": "type",
"@constants": "constant.groovy",
"@builtinFunctions": "constant.other.color",
"@default": "identifier",
},
},
],
[
/@symbols/,
{
cases: {
"@operators": "operator",
"@default": "",
},
},
],
],
common: [
// delimiters and operators
[/[()[\]]/, "@brackets"],
[/[<>](?!@symbols)/, "@brackets"],
[
/@symbols/,
{
cases: {
"@operators": "delimiter",
"@default": "",
},
},
],
[
/\/(?=([^\\/]|\\.)+\/([gimsuy]*)(\s*)(\.|;|\/|,|\)|\]|\}|$))/,
{ token: "regexp", bracket: "@open", next: "@regexp" },
],
// delimiter: after number because of .\d floats
[/[;,.]/, "delimiter"],
// strings
[/"([^"\\]|\\.)*$/, "string.invalid"],
[/'([^'\\]|\\.)*$/, "string.invalid"],
[/"/, "string", "@string_double"],
[/'/, "string", "@string_single"],
],
whitespace: [[/\s+/, "white"]],
comments: [
[/\/\/.*/, "comment"],
[
/\/\*/,
{
token: "comment.quote",
next: "@comment",
},
],
],
comment: [
[/[^*/]+/, "comment"],
[
/\*\//,
{
token: "comment.quote",
next: "@pop",
},
],
[/./, "comment"],
],
commentAnsi: [
[
/\/\*/,
{
token: "comment.quote",
next: "@comment",
},
],
[/[^*/]+/, "comment"],
[
/\*\//,
{
token: "comment.quote",
next: "@pop",
},
],
[/./, "comment"],
],
numbers: [
[/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?f?\b/, "number.float"],
[/[+-]?(?:0[obx])?\d+(?:u?[lst]?)?\b/, "number"],
],
regexp: [
[/(\{)(\d+(?:,\d*)?)(\})/, ["regexp.escape.control", "regexp.escape.control", "regexp.escape.control"]],
[
/(\[)(\^?)(?=(?:[^\]\\/]|\\.)+)/,
// @ts-ignore
["regexp.escape.control", { token: "regexp.escape.control", next: "@regexrange" }],
],
[/(\()(\?:|\?=|\?!)/, ["regexp.escape.control", "regexp.escape.control"]],
[/[()]/, "regexp.escape.control"],
[/@regexpctl/, "regexp.escape.control"],
[/[^\\/]/, "regexp"],
[/@regexpesc/, "regexp.escape"],
[/\\\./, "regexp.invalid"],
// @ts-ignore
[/(\/)([gimsuy]*)/, [{ token: "regexp", bracket: "@close", next: "@pop" }, "keyword.other"]],
],
regexrange: [
[/-/, "regexp.escape.control"],
[/\^/, "regexp.invalid"],
[/@regexpesc/, "regexp.escape"],
[/[^\]]/, "regexp"],
[/\]/, { token: "regexp.escape.control", next: "@pop", bracket: "@close" }],
],
embedded: [
[
/([^@]|^)([@]{4})*[@]{2}([@]([^@]|$)|[^@]|$)/,
{
token: "@rematch",
next: "@pop",
nextEmbedded: "@pop",
},
],
],
string_double: [
[/\$\{/, { token: "delimiter.bracket", next: "@bracketCounting" }],
[/[^\\"$]+/, "string"],
[/[^\\"]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, "string", "@pop"],
],
string_single: [
[/[^\\']+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/'/, "string", "@pop"],
],
string_backtick: [
[/\$\{/, { token: "delimiter.bracket", next: "@bracketCounting" }],
[/[^\\"$]+/, "string"],
[/@escapes/, "string.escape"],
[/\\./, "string.escape.invalid"],
[/"/, "string", "@pop"],
],
bracketCounting: [
[/\{/, "delimiter.bracket", "@bracketCounting"],
[/\}/, "delimiter.bracket", "@pop"],
{ include: "common" },
],
},
});
languages.setLanguageConfiguration(id, {
comments: {
lineComment: "//",
blockComment: ["/*", "*/"],
},
brackets,
autoClosingPairs,
surroundingPairs,
wordPattern,
});
};
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
how i use this file in react project