diff --git a/scripts/bundle.js b/scripts/bundle.js index 531a17c2..34f1527a 100644 --- a/scripts/bundle.js +++ b/scripts/bundle.js @@ -61,6 +61,7 @@ bundleOne('redshift/redshift'); bundleOne('pgsql/pgsql'); bundleOne('redis/redis'); bundleOne('csp/csp'); +bundleOne('scheme/scheme'); function bundleOne(moduleId, exclude) { requirejs.optimize({ diff --git a/src/monaco.contribution.ts b/src/monaco.contribution.ts index 340dddd3..f3fa2a34 100644 --- a/src/monaco.contribution.ts +++ b/src/monaco.contribution.ts @@ -44,3 +44,4 @@ import './swift/swift.contribution'; import './vb/vb.contribution'; import './xml/xml.contribution'; import './yaml/yaml.contribution'; +import './scheme/scheme.contribution'; diff --git a/src/scheme/scheme.contribution.ts b/src/scheme/scheme.contribution.ts new file mode 100644 index 00000000..ac8eb9b2 --- /dev/null +++ b/src/scheme/scheme.contribution.ts @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import { registerLanguage } from '../_.contribution'; + +// Allow for running under nodejs/requirejs in tests +const _monaco: typeof monaco = + typeof monaco === 'undefined' ? (self).monaco : monaco; + +registerLanguage({ + id: 'scheme', + extensions: ['.scm', '.ss', '.sch', '.rkt'], + aliases: ['scheme', 'Scheme'], + loader: () => _monaco.Promise.wrap(import('./scheme')), +}); diff --git a/src/scheme/scheme.test.ts b/src/scheme/scheme.test.ts new file mode 100644 index 00000000..4aaa04aa --- /dev/null +++ b/src/scheme/scheme.test.ts @@ -0,0 +1,91 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { testTokenization } from '../test/testRunner'; + +testTokenization('scheme', [ + // Keywords + [ + { + line: 'define-macro some', + tokens: [ + { startIndex: 0, type: 'keyword.scheme' }, + { startIndex: 12, type: 'white.scheme' }, + { startIndex: 13, type: 'variable.scheme' }, + ], + }, + ], + + // comments + [ + { + line: '; comment', + tokens: [{ startIndex: 0, type: 'comment.scheme' }], + }, + ], + [ + { + line: '|# comment', + tokens: [{ startIndex: 0, type: 'comment.scheme' }], + }, + { + line: 'multiline', + tokens: [{ startIndex: 0, type: 'comment.scheme' }], + }, + { + line: '#| cons', + tokens: [ + { startIndex: 0, type: 'comment.scheme' }, + { startIndex: 2, type: 'white.scheme' }, + { startIndex: 3, type: 'keyword.scheme' }, + ], + }, + ], + + // strings + [ + { + line: '"\\n string "', + tokens: [ + { startIndex: 0, type: 'string.scheme' }, + { startIndex: 1, type: 'string.escape.scheme' }, + { startIndex: 3, type: 'string.scheme' }, + ], + }, + ], + [ + { + line: '" string \\', + tokens: [{ startIndex: 0, type: 'string.scheme' }], + }, + { + line: 'multiline', + tokens: [{ startIndex: 0, type: 'string.scheme' }], + }, + { + line: ' ', + tokens: [ + // previous line needs to be terminated with \ + { startIndex: 0, type: 'white.scheme' }, + ], + }, + ], + + // numbers + [ + { + line: '1e2', + tokens: [{ startIndex: 0, type: 'number.float.scheme' }], + }, + ], + [ + { + line: '#x03BB', + tokens: [{ startIndex: 0, type: 'number.hex.scheme' }], + }, + ], +]); diff --git a/src/scheme/scheme.ts b/src/scheme/scheme.ts new file mode 100644 index 00000000..328d81ea --- /dev/null +++ b/src/scheme/scheme.ts @@ -0,0 +1,124 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration; +import ILanguage = monaco.languages.IMonarchLanguage; + +export const conf: IRichLanguageConfiguration = { + comments: { + lineComment: ';', + blockComment: ['#|', '|#'], + }, + + brackets: [['(', ')'], ['{', '}'], ['[', ']']], + + autoClosingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + ], + + surroundingPairs: [ + { open: '{', close: '}' }, + { open: '[', close: ']' }, + { open: '(', close: ')' }, + { open: '"', close: '"' }, + ], +}; + +export const language = { + defaultToken: '', + ignoreCase: true, + tokenPostfix: '.scheme', + + brackets: [ + { open: '(', close: ')', token: 'delimiter.parenthesis' }, + { open: '{', close: '}', token: 'delimiter.curly' }, + { open: '[', close: ']', token: 'delimiter.square' }, + ], + + keywords: [ + 'case', + 'do', + 'let', + 'loop', + 'if', + 'else', + 'when', + 'cons', + 'car', + 'cdr', + 'cond', + 'lambda', + 'lambda*', + 'syntax-rules', + 'format', + 'set!', + 'quote', + 'eval', + 'append', + 'list', + 'list?', + 'member?', + 'load', + ], + + constants: ['#t', '#f'], + + operators: ['eq?', 'eqv?', 'equal?', 'and', 'or', 'not', 'null?'], + + tokenizer: { + root: [ + [/#[xXoObB][0-9a-fA-F]+/, 'number.hex'], + [/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?/, 'number.float'], + + [/(?:\b(?:(define|define-syntax|define-macro))\b)(\s+)((?:\w|\-|\!|\?)*)/, ['keyword', 'white', 'variable']], + + [ + /[a-zA-Z_#][a-zA-Z0-9_\-\?\!\*]*/, + { + cases: { + '@keywords': 'keyword', + '@constants': 'constant', + '@operators': 'operators', + '@default': 'identifier', + }, + }, + ], + + { include: '@whitespace' }, + { include: '@strings' }, + ], + + comment: [ + [/[^\|#]+/, 'comment'], + [/\|\#/, 'comment', '@push'], + [/#\|/, 'comment', '@pop'], + [/[\|#]/, 'comment'], + ], + + whitespace: [ + [/[ \t\r\n]+/, 'white'], + [/\|\#/, 'comment', '@comment'], + [/;.*$/, 'comment'], + ], + + strings: [ + [/"$/, 'string', '@popall'], + [/"(?=.)/, 'string', '@multiLineString'], + ], + + multiLineString: [ + [/\\./, 'string.escape'], + [/"/, 'string', '@popall'], + [/.(?=.*")/, 'string'], + [/.*\\$/, 'string'], + [/.*$/, 'string', '@popall'], + ], + }, +}; diff --git a/test/setup.js b/test/setup.js index d797c473..a4c957b7 100644 --- a/test/setup.js +++ b/test/setup.js @@ -65,6 +65,7 @@ define(['require'], function (require) { 'release/dev/redis/redis.test', 'release/dev/csp/csp.test', 'release/dev/st/st.test', + 'release/dev/scheme/scheme.test', ], function () { run(); // We can launch the tests! }, function (err) {