/ concept-collection / numbl-web-ide
Sign in
concept-collection / numbl-web-ide
numbl-web-ide / src / numbl / language.ts
168 lines · 5.8 KBBlameHistoryRaw
1import { monaco } from 'minwebide';
2import { numblBuiltinNames } from './builtinNames';
4// MATLAB-syntax language support for .m files, adapted from numbl.org's own
5// Monaco language definition (numbl's src/numblLanguage.ts, which is not
6// published on npm). Registered after the built-in languages so its claim on
7// the .m extension takes precedence over VS Code's Objective-C mapping.
9const languageConfig: monaco.languages.LanguageConfiguration = {
10 comments: {
11 lineComment: '%',
12 blockComment: ['%{', '%}'],
13 },
14 brackets: [
15 ['{', '}'],
16 ['[', ']'],
17 ['(', ')'],
18 ],
19 autoClosingPairs: [
20 { open: '{', close: '}' },
21 { open: '[', close: ']' },
22 { open: '(', close: ')' },
23 { open: '"', close: '"' },
24 ],
25 surroundingPairs: [
26 { open: '{', close: '}' },
27 { open: '[', close: ']' },
28 { open: '(', close: ')' },
29 { open: '"', close: '"' },
30 ],
31};
33const builtinConstants = ['pi', 'e', 'eps', 'Inf', 'inf', 'NaN', 'nan', 'i', 'j'];
35// numbl's "special" builtins (I/O, plotting, path/fs commands) are dispatched
36// outside its regular builtin registry, so `numbl list-builtins` (the source
37// of builtinNames.ts) doesn't include them — copied from numbl 0.4.8's
38// SPECIAL_BUILTIN_NAMES plus the plot-dispatch names.
39const specialBuiltinNames = [
40 'help', 'disp', 'fprintf', 'arrayfun', 'cellfun', 'structfun', 'feval', 'bsxfun',
41 'subsref', 'subsasgn', 'builtin', 'fopen', 'fclose', 'fgetl', 'fgets', 'fileread',
42 'feof', 'ferror', 'fread', 'fwrite', 'frewind', 'fseek', 'ftell', 'fileparts',
43 'fullfile', 'assignin', 'evalin', 'set', 'get', 'drawnow', 'pause',
44 'plot', 'plot3', 'line', 'patch', 'trimesh', 'fill', 'surf', 'surface', 'scatter',
45 'imagesc', 'pcolor', 'contour', 'contourf', 'mesh', 'waterfall', 'isosurface',
46 'bar', 'barh', 'bar3', 'bar3h', 'stairs', 'errorbar', 'semilogx', 'semilogy',
47 'loglog', 'area', 'fplot', 'fplot3', 'scatter3', 'histogram', 'histogram2',
48 'boxchart', 'swarmchart', 'swarmchart3', 'piechart', 'donutchart', 'heatmap',
49 'quiver', 'quiver3', 'streamline', 'stream2', 'ishold', 'figure', 'uihtml',
50 'uigridlayout', 'subplot', 'tiledlayout', 'nexttile', 'title', 'xlabel', 'ylabel',
51 'zlabel', 'hold', 'grid', 'box', 'legend', 'close', 'sgtitle', 'shading', 'clf',
52 'cla', 'colormap', 'view', 'colorbar', 'axis', 'caxis', 'clim', 'gcf', 'gca',
53 'mfilename', 'addpath', 'rmpath', 'savepath', 'path', 'mkdir', 'websave',
54 'webread', 'delete', 'rmdir', 'movefile', 'copyfile', 'fileattrib', 'unzip',
55 'dir', 'warning', 'input', 'tempdir', 'tempname', 'userpath', 'getenv', 'setenv',
56 'pwd', 'cd', 'ode45', 'ode23', 'deval', 'tic', 'toc', 'quadgk', 'gmres', 'eigs',
57 'onCleanup',
58];
60function createTokensProvider(): monaco.languages.IMonarchLanguage {
61 return {
62 defaultToken: '',
64 keywords: [
65 'function', 'if', 'else', 'elseif', 'for', 'while', 'break', 'continue',
66 'return', 'end', 'classdef', 'properties', 'methods', 'events',
67 'enumeration', 'arguments', 'import', 'switch', 'case', 'otherwise',
68 'try', 'catch', 'global', 'persistent', 'true', 'false',
69 ],
71 builtinFunctions: [...new Set([...numblBuiltinNames, ...specialBuiltinNames])],
72 builtinConstants,
74 tokenizer: {
75 root: [
76 // section markers (must be at line start)
77 [/^%%.*$/, 'comment.doc'],
79 // block comments
80 [/%\{/, 'comment', '@blockComment'],
82 // line comments
83 [/%.*$/, 'comment'],
85 // identifiers and keywords — push afterValue since they produce values
86 [
87 /[a-zA-Z_]\w*/,
88 {
89 cases: {
90 '@keywords': { token: 'keyword', next: '@afterValue' },
91 '@builtinFunctions': { token: 'predefined', next: '@afterValue' },
92 '@builtinConstants': { token: 'constant.language', next: '@afterValue' },
93 '@default': { token: 'identifier', next: '@afterValue' },
94 },
95 },
96 ],
98 // numbers — push afterValue since they produce values
99 [/\d+\.?\d*([eE][+-]?\d+)?/, { token: 'number.float', next: '@afterValue' }],
100 [/\.\d+([eE][+-]?\d+)?/, { token: 'number.float', next: '@afterValue' }],
102 // strings (single and double quoted)
103 [/"([^"\\]|\\.)*$/, 'string.invalid'],
104 [/'([^'\\]|\\.)*$/, 'string.invalid'],
105 [/"/, 'string', '@doubleQuotedString'],
106 [/'/, 'string', '@singleQuotedString'],
108 // closing brackets produce values — push afterValue
109 [/[)\]]/, { token: '@brackets', next: '@afterValue' }],
110 [/\}/, { token: '@brackets', next: '@afterValue' }],
112 // opening brackets
113 [/[{([]/, '@brackets'],
115 // delimiters and operators (no ' — handled in afterValue as transpose)
116 [/[;,.]/, 'delimiter'],
117 [/==|~=|<=|>=|&&|\|\||\.\.\.|\.\*|\.\/|\.\\|\.\^|[=<>~+\-*/\\^&|!@?:]/, 'operator'],
119 { include: '@whitespace' },
120 ],
122 // state after a value-producing token (identifier, number, closing
123 // bracket, or string) — here ' is transpose, not a string delimiter
124 afterValue: [
125 [/\.'/, 'operator'],
126 [/'/, 'operator'],
127 [/$/, { token: '', next: '@pop' }],
128 [/(?=[\s\S])/, { token: '', next: '@pop' }],
129 ],
131 blockComment: [
132 [/%\}/, 'comment', '@pop'],
133 [/./, 'comment'],
134 ],
136 doubleQuotedString: [
137 [/[^\\"]+/, 'string'],
138 [/\\./, 'string.escape'],
139 [/"/, { token: 'string', switchTo: '@afterValue' }],
140 ],
142 singleQuotedString: [
143 [/[^\\']+/, 'string'],
144 [/''/, 'string.escape'],
145 [/'/, { token: 'string', switchTo: '@afterValue' }],
146 ],
148 whitespace: [[/[ \t\r\n]+/, 'white']],
149 },
150 };
153let registered = false;
155/** Registers MATLAB language support for .m files. Call once, after registerBuiltinLanguages. */
156export function registerMatlabLanguage(): void {
157 if (registered) {
158 return;
159 }
160 registered = true;
161 monaco.languages.register({
162 id: 'matlab',
163 extensions: ['.m'],
164 aliases: ['MATLAB', 'matlab'],
165 });
166 monaco.languages.setLanguageConfiguration('matlab', languageConfig);
167 monaco.languages.setMonarchTokensProvider('matlab', createTokensProvider());
moveopenescclose