Skip to content

Commit

Permalink
Improve syntax colorization
Browse files Browse the repository at this point in the history
Colorize aiming to replicate VSCode with the `Dark +` theme.
Define a theme to provide the missing color for function names and adapt the color for keywords.
  • Loading branch information
Viir committed Aug 17, 2020
1 parent 01ffd76 commit 8ce434b
Show file tree
Hide file tree
Showing 3 changed files with 254 additions and 4 deletions.
12 changes: 11 additions & 1 deletion implement/elm-editor-server/src/Backend/Main.elm
Original file line number Diff line number Diff line change
Expand Up @@ -362,12 +362,22 @@ monacoHtmlDocumentFromCdnUrl cdnUrlToMin =
monaco.languages.setMonarchTokensProvider('Elm', window.elm_monarch);
monaco.editor.defineTheme('dark-plus', {
base: 'vs-dark',
inherit: true,
rules: [
{ token: 'keyword', foreground: '#C586C0' },
{ token: 'type', foreground: '#569CD6' },
{ token: 'function.name', foreground: '#DCDCAA' },
]
});
var editor = monaco.editor.create(document.getElementById('container'), {
value: "Initialization of editor is not complete yet",
language: 'Elm',
automaticLayout: true,
scrollBeyondLastLine: false,
theme: "vs-dark"
theme: "dark-plus"
});
tryCompleteSetup();
Expand Down
212 changes: 212 additions & 0 deletions implement/elm-editor-server/src/Test/monaco-playground.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@

var elm_monarch = {
// Set defaultToken to invalid to see what you do not tokenize yet
// defaultToken: 'invalid',

keywords: [
'if', 'then', 'else',
'case', 'of',
'let', 'in',
'module', 'import', 'exposing',
'port',
'as',
'_'
],

typeKeywords: [
'type', 'alias'
],

operators: [
'=', '>', '<', '==', '<=', '>=', '/=',
'&&', '||', '++', '+', '-', '*', '/', '//',
'<<', '>>'
],

// we include these common regular expressions
symbols: /[=><!~?:&|+\-*\/\^%]+/,

// C# style strings
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,

// The main tokenizer for our languages
tokenizer: {
root: [
[/^[a-z_$][\w$]*/, {
cases: {
'@typeKeywords': 'type',
'@keywords': 'keyword',
'@default': 'function.name'
}
}
],

[/[a-z_$][\w$]*/, {
cases: {
'exposing': { token: 'keyword', next: '@after_keyword_exposing' },
'@typeKeywords': 'type',
'@keywords': 'keyword',
'@default': 'identifier'
}
}],


[/[A-Z][\w\$]*/, 'type.identifier'], // to show class names nicely

// whitespace
{ include: '@whitespace' },

// delimiters and operators
[/[{}()\[\]]/, '@brackets'],
[/[<>](?!@symbols)/, '@brackets'],
[/@symbols/, {
cases: {
'@operators': 'operator',
'@default': ''
}
}],

// @ annotations.
// As an example, we emit a debugging log message on these tokens.
// Note: message are supressed during the first load -- change some lines to see them.
[/@\s*[a-zA-Z_\$][\w\$]*/, { token: 'annotation', log: 'annotation token: $0' }],

// numbers
[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
[/0[xX][0-9a-fA-F]+/, 'number.hex'],
[/\d+/, 'number'],

// delimiter: after number because of .\d floats
[/[;,.]/, 'delimiter'],

// strings
[/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
[/"/, { token: 'string.quote', bracket: '@open', next: '@string' }],

// characters
[/'[^\\']'/, 'string'],
[/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
[/'/, 'string.invalid']
],

comment: [
[/{-/, 'comment', '@push'], // nested comment
[/-}/, 'comment', '@pop'],
[/./, 'comment.content']
],

after_keyword_exposing:
[
[/\(/, { token: 'delimiter', switchTo: 'exposing' }],
[/$/, { token: 'whitespace', next: '@popall' }],
[/^[a-z]/, { token: 'whitespace', next: '@popall' }],
[/\)/, { token: 'delimiter', next: '@pop' }],
],

exposing:
[
[/\)/, { token: 'delimiter', next: '@pop' }],
[/$/, { token: 'whitespace', next: '@popall' }],
[/^[a-z]/, { token: 'whitespace', next: '@popall' }],
[/[A-Z_$][\w$]*/, { token: 'type' }],
[/[a-z_$][\w$]*/, { token: 'function.name' }],
[/\(/, { token: 'delimiter', next: '@push' }],
],

string: [
[/[^\\"]+/, 'string'],
[/@escapes/, 'string.escape'],
[/\\./, 'string.escape.invalid'],
[/"/, { token: 'string.quote', bracket: '@close', next: '@pop' }]
],

string_triple_quote: [
[/"""/, 'string', '@pop'],
[/./, 'string']
],

whitespace: [
[/[ \t\r\n]+/, 'white'],
[/{-/, 'comment', '@comment'],
[/--.*$/, 'comment'],
[/"""/, 'string', '@string_triple_quote'],
],
},
};

monaco.languages.register({ id: 'Elm' });

monaco.languages.setMonarchTokensProvider('Elm', elm_monarch);

monaco.editor.defineTheme('dark-plus', {
base: 'vs-dark',
inherit: true,
rules: [
{ token: 'keyword', foreground: '#C586C0' },
{ token: 'type', foreground: '#569CD6' },
{ token: 'function.name', foreground: '#DCDCAA' },
]
});

monaco.editor.create(document.getElementById("container"), {
theme: 'dark-plus',
value: getCode(),
language: 'Elm'
});

function getCode() {
return `
module Test.TestSyntaxHighlighting exposing
( RecordAlias
, Route(..)
, functionWithLetBlockAndLocalFunction
, reference
)
import Bytes
import Json.Decode exposing (keyValuePairs)
type Route
= ApiRoute
| StaticFileRoute String
type alias RecordAlias typeVar =
{ primitiveField : Basics.Int
, var : typeVar
-- Single line comment
}
functionWithLetBlockAndLocalFunction : Bytes.Bytes -> Int
functionWithLetBlockAndLocalFunction param =
let
{- Multi-line
comment
{- nested -}
-}
localFunction : Bytes.Bytes -> Int
localFunction =
Bytes.width
in
if (param |> localFunction) < 123 then
"testing string literal" ++ """string literal
containing newline""" |> String.length
else
case "hello" of
"specific case" ->
1
_ ->
3
reference : Json.Decode.Decoder a -> Json.Decode.Decoder (List ( String, a ))
reference =
keyValuePairs
`;
}
34 changes: 31 additions & 3 deletions implement/elm-editor-server/src/monarch.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

var elm_monarch = {
// Set defaultToken to invalid to see what you do not tokenize yet
// defaultToken: 'invalid',
Expand Down Expand Up @@ -32,14 +31,25 @@ var elm_monarch = {
// The main tokenizer for our languages
tokenizer: {
root: [
// identifiers and keywords
[/^[a-z_$][\w$]*/, {
cases: {
'@typeKeywords': 'type',
'@keywords': 'keyword',
'@default': 'function.name'
}
}
],

[/[a-z_$][\w$]*/, {
cases: {
'@typeKeywords': 'keyword',
'exposing': { token: 'keyword', next: '@after_keyword_exposing' },
'@typeKeywords': 'type',
'@keywords': 'keyword',
'@default': 'identifier'
}
}],


[/[A-Z][\w\$]*/, 'type.identifier'], // to show class names nicely

// whitespace
Expand Down Expand Up @@ -84,6 +94,24 @@ var elm_monarch = {
[/./, 'comment.content']
],

after_keyword_exposing:
[
[/\(/, { token: 'delimiter', switchTo: 'exposing' }],
[/$/, { token: 'whitespace', next: '@popall' }],
[/^[a-z]/, { token: 'whitespace', next: '@popall' }],
[/\)/, { token: 'delimiter', next: '@pop' }],
],

exposing:
[
[/\)/, { token: 'delimiter', next: '@pop' }],
[/$/, { token: 'whitespace', next: '@popall' }],
[/^[a-z]/, { token: 'whitespace', next: '@popall' }],
[/[A-Z_$][\w$]*/, { token: 'type' }],
[/[a-z_$][\w$]*/, { token: 'function.name' }],
[/\(/, { token: 'delimiter', next: '@push' }],
],

string: [
[/[^\\"]+/, 'string'],
[/@escapes/, 'string.escape'],
Expand Down

0 comments on commit 8ce434b

Please sign in to comment.