├── .editorconfig
├── .gitignore
├── .vscodeignore
├── BUILD.md
├── CHANGELOG.md
├── LICENSE
├── assets
├── icon.png
├── icon.svg
└── sample.png
├── extension
└── extension.ts
├── icons
└── rhai.png
├── package.json
├── readme.md
├── syntax
├── rhai.JSON-tmLanguage
├── rhai.YAML-tmLanguage
├── rhai.configuration.json
├── rhai.markdown.json
└── rhai.tmLanguage.json
├── test
├── array.rhai
├── assignment.rhai
├── comments.rhai
├── doc-comments.rhai
├── fibonacci.rhai
├── for1.rhai
├── for2.rhai
├── for3.rhai
├── function_decl1.rhai
├── function_decl2.rhai
├── function_decl3.rhai
├── function_decl4.rhai
├── if1.rhai
├── if2.rhai
├── loop.rhai
├── mat_mul.rhai
├── module.rhai
├── oop.rhai
├── op1.rhai
├── op2.rhai
├── op3.rhai
├── primes.rhai
├── speed_test.rhai
├── string.rhai
├── strings_map.rhai
├── switch.rhai
└── while.rhai
├── tsconfig.json
└── tslint.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | charset = utf-8
3 | indent_style = space
4 | indent_size = 4
5 | tab_width = 4
6 | insert_final_newline = true
7 | trim_trailing_whitespace = true
8 |
9 | [*.YAML-tmLanguage]
10 | indent_style = space
11 | indent_size = 2
12 |
13 | [*.{json,awsl}]
14 | indent_style = space
15 | indent_size = 4
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # IDEs
2 | .vscode
3 | .idea
4 | .vs
5 | *.iml
6 |
7 | # Node
8 | node_modules/
9 | dist/
10 | package-lock.json
11 | yarn.lock
12 | yarn-error.log
13 |
14 | # Release
15 | .vsixmanifest
16 | *.vsix
17 | *.tgz
18 | *.nb
19 | *.ps1
20 |
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | source/**/*
3 | images/**/*
4 | test/**/*
5 |
6 | .vscode
7 | .gitignore
8 |
9 | *.tgz
10 | **/*.ai
11 | yarn*
12 |
13 | **/*.ts
14 | **/ts*.json
15 | BUILD.md
16 | **/*.vsix
17 |
--------------------------------------------------------------------------------
/BUILD.md:
--------------------------------------------------------------------------------
1 | How to Build Extension from Source
2 | =================================
3 |
4 | Prerequisites
5 | -------------
6 |
7 | - Install [Node.js](https://nodejs.org)
8 |
9 | - Install [TypeScript](https://www.typescriptlang.org)
10 |
11 | ```sh
12 | npm install -g typescript
13 | ```
14 |
15 | - Install [VSCE](https://github.com/Microsoft/vscode-vsce)
16 |
17 | ```sh
18 | npm install -g vsce
19 | ```
20 |
21 | Fetch Node packages
22 | -------------------
23 |
24 | ```sh
25 | npm install
26 | ```
27 |
28 | Compile with TypeScript
29 | -----------------------
30 |
31 | ```sh
32 | tsc
33 | ```
34 |
35 | Compiled files are in the `dist` directory.
36 |
37 | Build VSIX package
38 | ------------------
39 |
40 | ```sh
41 | vsce package
42 | ```
43 |
44 | Compiled package is `vscode-rhai-`_version_`.vsix` within the main directory.
45 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Version 0.6.7
2 | =============
3 |
4 | * Fixed recognition for `..=` (inclusive range) operator.
5 | * Fixed parsing for `|` in `switch` case conditions (previously parses as a closure).
6 | * White-spaces no longer highlights.
7 |
8 |
9 | Version 0.6.6
10 | =============
11 |
12 | * Add the range operator `..`
13 | * Add elvis operators.
14 |
15 |
16 | Version 0.6.5
17 | =============
18 |
19 | * Fix Highlighting styles of `private` and `fn`.
20 | * Recognize `Fn` as a reserved keyword.
21 |
22 |
23 | Version 0.6.4
24 | =============
25 |
26 | * Remove keywords that are no longer reserved.
27 |
28 |
29 | Version 0.6.3
30 | =============
31 |
32 | * Support untrusted workspaces.
33 | * Refine styling of automatic `global` modules.
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | ### 1. Definitions
5 |
6 | **1.1. “Contributor”**
7 | means each individual or legal entity that creates, contributes to
8 | the creation of, or owns Covered Software.
9 |
10 | **1.2. “Contributor Version”**
11 | means the combination of the Contributions of others (if any) used
12 | by a Contributor and that particular Contributor's Contribution.
13 |
14 | **1.3. “Contribution”**
15 | means Covered Software of a particular Contributor.
16 |
17 | **1.4. “Covered Software”**
18 | means Source Code Form to which the initial Contributor has attached
19 | the notice in Exhibit A, the Executable Form of such Source Code
20 | Form, and Modifications of such Source Code Form, in each case
21 | including portions thereof.
22 |
23 | **1.5. “Incompatible With Secondary Licenses”**
24 | means
25 |
26 | * **(a)** that the initial Contributor has attached the notice described
27 | in Exhibit B to the Covered Software; or
28 | * **(b)** that the Covered Software was made available under the terms of
29 | version 1.1 or earlier of the License, but not also under the
30 | terms of a Secondary License.
31 |
32 | **1.6. “Executable Form”**
33 | means any form of the work other than Source Code Form.
34 |
35 | **1.7. “Larger Work”**
36 | means a work that combines Covered Software with other material, in
37 | a separate file or files, that is not Covered Software.
38 |
39 | **1.8. “License”**
40 | means this document.
41 |
42 | **1.9. “Licensable”**
43 | means having the right to grant, to the maximum extent possible,
44 | whether at the time of the initial grant or subsequently, any and
45 | all of the rights conveyed by this License.
46 |
47 | **1.10. “Modifications”**
48 | means any of the following:
49 |
50 | * **(a)** any file in Source Code Form that results from an addition to,
51 | deletion from, or modification of the contents of Covered
52 | Software; or
53 | * **(b)** any new file in Source Code Form that contains any Covered
54 | Software.
55 |
56 | **1.11. “Patent Claims” of a Contributor**
57 | means any patent claim(s), including without limitation, method,
58 | process, and apparatus claims, in any patent Licensable by such
59 | Contributor that would be infringed, but for the grant of the
60 | License, by the making, using, selling, offering for sale, having
61 | made, import, or transfer of either its Contributions or its
62 | Contributor Version.
63 |
64 | **1.12. “Secondary License”**
65 | means either the GNU General Public License, Version 2.0, the GNU
66 | Lesser General Public License, Version 2.1, the GNU Affero General
67 | Public License, Version 3.0, or any later versions of those
68 | licenses.
69 |
70 | **1.13. “Source Code Form”**
71 | means the form of the work preferred for making modifications.
72 |
73 | **1.14. “You” (or “Your”)**
74 | means an individual or a legal entity exercising rights under this
75 | License. For legal entities, “You” includes any entity that
76 | controls, is controlled by, or is under common control with You. For
77 | purposes of this definition, “control” means **(a)** the power, direct
78 | or indirect, to cause the direction or management of such entity,
79 | whether by contract or otherwise, or **(b)** ownership of more than
80 | fifty percent (50%) of the outstanding shares or beneficial
81 | ownership of such entity.
82 |
83 |
84 | ### 2. License Grants and Conditions
85 |
86 | #### 2.1. Grants
87 |
88 | Each Contributor hereby grants You a world-wide, royalty-free,
89 | non-exclusive license:
90 |
91 | * **(a)** under intellectual property rights (other than patent or trademark)
92 | Licensable by such Contributor to use, reproduce, make available,
93 | modify, display, perform, distribute, and otherwise exploit its
94 | Contributions, either on an unmodified basis, with Modifications, or
95 | as part of a Larger Work; and
96 | * **(b)** under Patent Claims of such Contributor to make, use, sell, offer
97 | for sale, have made, import, and otherwise transfer either its
98 | Contributions or its Contributor Version.
99 |
100 | #### 2.2. Effective Date
101 |
102 | The licenses granted in Section 2.1 with respect to any Contribution
103 | become effective for each Contribution on the date the Contributor first
104 | distributes such Contribution.
105 |
106 | #### 2.3. Limitations on Grant Scope
107 |
108 | The licenses granted in this Section 2 are the only rights granted under
109 | this License. No additional rights or licenses will be implied from the
110 | distribution or licensing of Covered Software under this License.
111 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
112 | Contributor:
113 |
114 | * **(a)** for any code that a Contributor has removed from Covered Software;
115 | or
116 | * **(b)** for infringements caused by: **(i)** Your and any other third party's
117 | modifications of Covered Software, or **(ii)** the combination of its
118 | Contributions with other software (except as part of its Contributor
119 | Version); or
120 | * **(c)** under Patent Claims infringed by Covered Software in the absence of
121 | its Contributions.
122 |
123 | This License does not grant any rights in the trademarks, service marks,
124 | or logos of any Contributor (except as may be necessary to comply with
125 | the notice requirements in Section 3.4).
126 |
127 | #### 2.4. Subsequent Licenses
128 |
129 | No Contributor makes additional grants as a result of Your choice to
130 | distribute the Covered Software under a subsequent version of this
131 | License (see Section 10.2) or under the terms of a Secondary License (if
132 | permitted under the terms of Section 3.3).
133 |
134 | #### 2.5. Representation
135 |
136 | Each Contributor represents that the Contributor believes its
137 | Contributions are its original creation(s) or it has sufficient rights
138 | to grant the rights to its Contributions conveyed by this License.
139 |
140 | #### 2.6. Fair Use
141 |
142 | This License is not intended to limit any rights You have under
143 | applicable copyright doctrines of fair use, fair dealing, or other
144 | equivalents.
145 |
146 | #### 2.7. Conditions
147 |
148 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
149 | in Section 2.1.
150 |
151 |
152 | ### 3. Responsibilities
153 |
154 | #### 3.1. Distribution of Source Form
155 |
156 | All distribution of Covered Software in Source Code Form, including any
157 | Modifications that You create or to which You contribute, must be under
158 | the terms of this License. You must inform recipients that the Source
159 | Code Form of the Covered Software is governed by the terms of this
160 | License, and how they can obtain a copy of this License. You may not
161 | attempt to alter or restrict the recipients' rights in the Source Code
162 | Form.
163 |
164 | #### 3.2. Distribution of Executable Form
165 |
166 | If You distribute Covered Software in Executable Form then:
167 |
168 | * **(a)** such Covered Software must also be made available in Source Code
169 | Form, as described in Section 3.1, and You must inform recipients of
170 | the Executable Form how they can obtain a copy of such Source Code
171 | Form by reasonable means in a timely manner, at a charge no more
172 | than the cost of distribution to the recipient; and
173 |
174 | * **(b)** You may distribute such Executable Form under the terms of this
175 | License, or sublicense it under different terms, provided that the
176 | license for the Executable Form does not attempt to limit or alter
177 | the recipients' rights in the Source Code Form under this License.
178 |
179 | #### 3.3. Distribution of a Larger Work
180 |
181 | You may create and distribute a Larger Work under terms of Your choice,
182 | provided that You also comply with the requirements of this License for
183 | the Covered Software. If the Larger Work is a combination of Covered
184 | Software with a work governed by one or more Secondary Licenses, and the
185 | Covered Software is not Incompatible With Secondary Licenses, this
186 | License permits You to additionally distribute such Covered Software
187 | under the terms of such Secondary License(s), so that the recipient of
188 | the Larger Work may, at their option, further distribute the Covered
189 | Software under the terms of either this License or such Secondary
190 | License(s).
191 |
192 | #### 3.4. Notices
193 |
194 | You may not remove or alter the substance of any license notices
195 | (including copyright notices, patent notices, disclaimers of warranty,
196 | or limitations of liability) contained within the Source Code Form of
197 | the Covered Software, except that You may alter any license notices to
198 | the extent required to remedy known factual inaccuracies.
199 |
200 | #### 3.5. Application of Additional Terms
201 |
202 | You may choose to offer, and to charge a fee for, warranty, support,
203 | indemnity or liability obligations to one or more recipients of Covered
204 | Software. However, You may do so only on Your own behalf, and not on
205 | behalf of any Contributor. You must make it absolutely clear that any
206 | such warranty, support, indemnity, or liability obligation is offered by
207 | You alone, and You hereby agree to indemnify every Contributor for any
208 | liability incurred by such Contributor as a result of warranty, support,
209 | indemnity or liability terms You offer. You may include additional
210 | disclaimers of warranty and limitations of liability specific to any
211 | jurisdiction.
212 |
213 |
214 | ### 4. Inability to Comply Due to Statute or Regulation
215 |
216 | If it is impossible for You to comply with any of the terms of this
217 | License with respect to some or all of the Covered Software due to
218 | statute, judicial order, or regulation then You must: **(a)** comply with
219 | the terms of this License to the maximum extent possible; and **(b)**
220 | describe the limitations and the code they affect. Such description must
221 | be placed in a text file included with all distributions of the Covered
222 | Software under this License. Except to the extent prohibited by statute
223 | or regulation, such description must be sufficiently detailed for a
224 | recipient of ordinary skill to be able to understand it.
225 |
226 |
227 | ### 5. Termination
228 |
229 | **5.1.** The rights granted under this License will terminate automatically
230 | if You fail to comply with any of its terms. However, if You become
231 | compliant, then the rights granted under this License from a particular
232 | Contributor are reinstated **(a)** provisionally, unless and until such
233 | Contributor explicitly and finally terminates Your grants, and **(b)** on an
234 | ongoing basis, if such Contributor fails to notify You of the
235 | non-compliance by some reasonable means prior to 60 days after You have
236 | come back into compliance. Moreover, Your grants from a particular
237 | Contributor are reinstated on an ongoing basis if such Contributor
238 | notifies You of the non-compliance by some reasonable means, this is the
239 | first time You have received notice of non-compliance with this License
240 | from such Contributor, and You become compliant prior to 30 days after
241 | Your receipt of the notice.
242 |
243 | **5.2.** If You initiate litigation against any entity by asserting a patent
244 | infringement claim (excluding declaratory judgment actions,
245 | counter-claims, and cross-claims) alleging that a Contributor Version
246 | directly or indirectly infringes any patent, then the rights granted to
247 | You by any and all Contributors for the Covered Software under Section
248 | 2.1 of this License shall terminate.
249 |
250 | **5.3.** In the event of termination under Sections 5.1 or 5.2 above, all
251 | end user license agreements (excluding distributors and resellers) which
252 | have been validly granted by You or Your distributors under this License
253 | prior to termination shall survive termination.
254 |
255 |
256 | ### 6. Disclaimer of Warranty
257 |
258 | > Covered Software is provided under this License on an “as is”
259 | > basis, without warranty of any kind, either expressed, implied, or
260 | > statutory, including, without limitation, warranties that the
261 | > Covered Software is free of defects, merchantable, fit for a
262 | > particular purpose or non-infringing. The entire risk as to the
263 | > quality and performance of the Covered Software is with You.
264 | > Should any Covered Software prove defective in any respect, You
265 | > (not any Contributor) assume the cost of any necessary servicing,
266 | > repair, or correction. This disclaimer of warranty constitutes an
267 | > essential part of this License. No use of any Covered Software is
268 | > authorized under this License except under this disclaimer.
269 |
270 | ### 7. Limitation of Liability
271 |
272 | > Under no circumstances and under no legal theory, whether tort
273 | > (including negligence), contract, or otherwise, shall any
274 | > Contributor, or anyone who distributes Covered Software as
275 | > permitted above, be liable to You for any direct, indirect,
276 | > special, incidental, or consequential damages of any character
277 | > including, without limitation, damages for lost profits, loss of
278 | > goodwill, work stoppage, computer failure or malfunction, or any
279 | > and all other commercial damages or losses, even if such party
280 | > shall have been informed of the possibility of such damages. This
281 | > limitation of liability shall not apply to liability for death or
282 | > personal injury resulting from such party's negligence to the
283 | > extent applicable law prohibits such limitation. Some
284 | > jurisdictions do not allow the exclusion or limitation of
285 | > incidental or consequential damages, so this exclusion and
286 | > limitation may not apply to You.
287 |
288 |
289 | ### 8. Litigation
290 |
291 | Any litigation relating to this License may be brought only in the
292 | courts of a jurisdiction where the defendant maintains its principal
293 | place of business and such litigation shall be governed by laws of that
294 | jurisdiction, without reference to its conflict-of-law provisions.
295 | Nothing in this Section shall prevent a party's ability to bring
296 | cross-claims or counter-claims.
297 |
298 |
299 | ### 9. Miscellaneous
300 |
301 | This License represents the complete agreement concerning the subject
302 | matter hereof. If any provision of this License is held to be
303 | unenforceable, such provision shall be reformed only to the extent
304 | necessary to make it enforceable. Any law or regulation which provides
305 | that the language of a contract shall be construed against the drafter
306 | shall not be used to construe this License against a Contributor.
307 |
308 |
309 | ### 10. Versions of the License
310 |
311 | #### 10.1. New Versions
312 |
313 | Mozilla Foundation is the license steward. Except as provided in Section
314 | 10.3, no one other than the license steward has the right to modify or
315 | publish new versions of this License. Each version will be given a
316 | distinguishing version number.
317 |
318 | #### 10.2. Effect of New Versions
319 |
320 | You may distribute the Covered Software under the terms of the version
321 | of the License under which You originally received the Covered Software,
322 | or under the terms of any subsequent version published by the license
323 | steward.
324 |
325 | #### 10.3. Modified Versions
326 |
327 | If you create software not governed by this License, and you want to
328 | create a new license for such software, you may create and use a
329 | modified version of this License if you rename the license and remove
330 | any references to the name of the license steward (except to note that
331 | such modified license differs from this License).
332 |
333 | #### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
334 |
335 | If You choose to distribute Source Code Form that is Incompatible With
336 | Secondary Licenses under the terms of this version of the License, the
337 | notice described in Exhibit B of this License must be attached.
338 |
339 | ## Exhibit A - Source Code Form License Notice
340 |
341 | This Source Code Form is subject to the terms of the Mozilla Public
342 | License, v. 2.0. If a copy of the MPL was not distributed with this
343 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
344 |
345 | If it is not possible or desirable to put the notice in a particular
346 | file, then You may include the notice in a location (such as a LICENSE
347 | file in a relevant directory) where a recipient would be likely to look
348 | for such a notice.
349 |
350 | You may add additional accurate notices of copyright ownership.
351 |
352 | ## Exhibit B - “Incompatible With Secondary Licenses” Notice
353 |
354 | This Source Code Form is "Incompatible With Secondary Licenses", as
355 | defined by the Mozilla Public License, v. 2.0.
356 |
357 |
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rhaiscript/vscode-rhai/e8c9e59963382613bffda137bc509f38ad64c78c/assets/icon.png
--------------------------------------------------------------------------------
/assets/icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
--------------------------------------------------------------------------------
/assets/sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rhaiscript/vscode-rhai/e8c9e59963382613bffda137bc509f38ad64c78c/assets/sample.png
--------------------------------------------------------------------------------
/extension/extension.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from 'vscode'
2 | import * as child_process from 'child_process'
3 |
4 | import
5 | {
6 | LanguageClient,
7 | LanguageClientOptions,
8 | Executable,
9 | } from 'vscode-languageclient'
10 |
11 |
12 | let client: LanguageClient
13 |
14 | function start_client()
15 | {
16 | let serverOptions: Executable = {
17 | command: 'rhai-lsp',
18 | }
19 |
20 | let clientOptions: LanguageClientOptions = {
21 | documentSelector: [{ scheme: 'file', language: 'rhai' }],
22 | }
23 |
24 | client = new LanguageClient(
25 | 'rhaiLanguageServer',
26 | 'Rhai Language Server',
27 | serverOptions,
28 | clientOptions,
29 | )
30 |
31 | client.start()
32 | }
33 |
34 |
35 | async function is_installed(cmd: string): Promise
36 | {
37 | return new Promise((resolve) =>
38 | {
39 | const checkCommand = process.platform === 'win32' ? 'where' : 'command -v'
40 | const proc = child_process.exec(`${checkCommand} ${cmd}`)
41 | proc.on('exit', (code) => { resolve(code === 0) })
42 | })
43 | }
44 |
45 | async function installServerBinary(): Promise
46 | {
47 | await is_installed('cargo')
48 | // cargo install
49 | // download from github
50 | const task = new vscode.Task(
51 | { type: 'cargo', task: 'install' },
52 | vscode.workspace.workspaceFolders![0],
53 | 'Installing lsp server',
54 | 'rhai-lsp',
55 | new vscode.ShellExecution('cargo install rhai-lsp'),
56 | )
57 | const promise = new Promise((resolve) =>
58 | {
59 | vscode.tasks.onDidEndTask((e) =>
60 | {
61 | if (e.execution.task === task) {
62 | e.execution.terminate()
63 | }
64 | })
65 | vscode.tasks.onDidEndTaskProcess((e) =>
66 | {
67 | resolve(e.exitCode === 0)
68 | })
69 | })
70 | vscode.tasks.executeTask(task)
71 |
72 | return promise
73 | }
74 |
75 | async function tryToInstallLanguageServer(configuration: vscode.WorkspaceConfiguration)
76 | {
77 | const selected = await vscode.window.showInformationMessage(
78 | 'Install rhai-lsp-server (Rust toolchain required) ?',
79 | 'Install',
80 | 'Never',
81 | )
82 | if (selected === 'Install') {
83 | const installed = await installServerBinary()
84 | if (installed) {
85 | start_client()
86 | }
87 | }
88 | else if (selected === 'Never') {
89 | configuration.update('useLanguageServer', false)
90 | }
91 | }
92 |
93 | export async function activate(context: vscode.ExtensionContext)
94 | {
95 | const configuration = vscode.workspace.getConfiguration('notedown')
96 | const useLanguageServer = configuration.get('useLanguageServer')
97 | const shouldStartClient = useLanguageServer && (await is_installed('rhai-lsp'))
98 | if (shouldStartClient) {
99 | start_client()
100 | } else if (useLanguageServer) {
101 | // tryToInstallLanguageServer(configuration)
102 | }
103 | }
104 |
105 | export function deactivate(): Thenable | undefined
106 | {
107 | if (!client) {
108 | return undefined
109 | }
110 | return client.stop()
111 | }
112 |
--------------------------------------------------------------------------------
/icons/rhai.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rhaiscript/vscode-rhai/e8c9e59963382613bffda137bc509f38ad64c78c/icons/rhai.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vscode-rhai",
3 | "private": true,
4 | "displayName": "Rhai Language Support",
5 | "description": "Syntax highlighting for Rhai scripts",
6 | "publisher": "rhaiscript",
7 | "version": "0.6.8",
8 | "icon": "assets/icon.png",
9 | "homepage": "https://rhai.rs",
10 | "bugs": {
11 | "url": "https://github.com/rhaiscript/vscode-rhai/issues"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/rhaiscript/vscode-rhai.git"
16 | },
17 | "categories": [
18 | "Programming Languages",
19 | "Formatters"
20 | ],
21 | "capabilities": {
22 | "untrustedWorkspaces": {
23 | "supported": true
24 | }
25 | },
26 | "scripts": {
27 | "build:syntax": "ts-node syntax/build.ts",
28 | "build:ts": "tsc -b",
29 | "build": "wee build:syntax -t && wee build:ts -t",
30 | "pack": "wee build && vsce package",
31 | "lint": "tslint **/*.ts --fix"
32 | },
33 | "main": "./dist/extension.js",
34 | "engines": {
35 | "vscode": "^1.30.0"
36 | },
37 | "activationEvents": [
38 | "onLanguage:rhai"
39 | ],
40 | "contributes": {
41 | "languages": [
42 | {
43 | "id": "rhai",
44 | "aliases": [
45 | "Rhai"
46 | ],
47 | "extensions": [
48 | ".rhai"
49 | ],
50 | "filenames": [],
51 | "filenamePatterns": [],
52 | "mimetypes": [],
53 | "icon": {
54 | "light": "./icons/rhai.png",
55 | "dark": "./icons/rhai.png"
56 | },
57 | "configuration": "./syntax/rhai.configuration.json"
58 | }
59 | ],
60 | "grammars": [
61 | {
62 | "language": "rhai",
63 | "scopeName": "source.rhai",
64 | "path": "./syntax/rhai.tmLanguage.json"
65 | },
66 | {
67 | "scopeName": "markdown.rhai.codeblock",
68 | "path": "./syntax/rhai.markdown.json",
69 | "injectTo": [
70 | "text.html.markdown"
71 | ],
72 | "embeddedLanguages": {
73 | "meta.embedded.block.rhai": "rhai"
74 | }
75 | }
76 | ],
77 | "commands": [
78 | {
79 | "command": "rhai.format",
80 | "title": "Rhai: Format File"
81 | }
82 | ],
83 | "configuration": {
84 | "title": "Rhai",
85 | "properties": {
86 | "rhai.useLanguageServer": {
87 | "type": "boolean",
88 | "default": true,
89 | "description": "Use Rhai Language Server"
90 | },
91 | "rhai.trace.server": {
92 | "type": "string",
93 | "default": "off",
94 | "enum": [
95 | "off",
96 | "messages",
97 | "verbose"
98 | ],
99 | "description": "Traces the communication between VS Code and the language server.",
100 | "scope": "window"
101 | }
102 | }
103 | }
104 | },
105 | "dependencies": {
106 | "vscode-languageclient": "^6.1.3"
107 | },
108 | "devDependencies": {
109 | "@types/node": "^11.13.6",
110 | "@types/vscode": "^1.30.0",
111 | "tslint": "^6.0.0",
112 | "typescript": "^3.8.2"
113 | }
114 | }
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | Rhai Language Support for Visual Studio Code
2 | ===========================================
3 |
4 | [](https://github.com/rhaiscript/vscode-rhai/blob/master/LICENSE.md)
5 | [](https://marketplace.visualstudio.com/items?itemName=rhaiscript.vscode-rhai)
6 | [](https://github.com/rhaiscript/vscode-rhai/releases/latest)
7 |
8 | [](https://rhai.rs)
9 |
10 | [Rhai](https://rhai.rs) is an embedded scripting language and evaluation engine for Rust that gives
11 | a safe and easy way to add scripting to any application.
12 |
13 |
14 | Features
15 | --------
16 |
17 | - [x] Syntax highlighting
18 |
19 |
20 | Todo List
21 | ---------
22 |
23 | - [ ] Auto formatter
24 | - [ ] Language server
25 |
26 |
27 | How to Install
28 | --------------
29 |
30 | - Search for `Rhai Language Support` in Visual Studio Code.
31 |
32 | - Download directly from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=rhaiscript.vscode-rhai).
33 |
34 |
35 | Screenshot
36 | ----------
37 |
38 | 
39 |
--------------------------------------------------------------------------------
/syntax/rhai.JSON-tmLanguage:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Rhai",
3 | "version": "v0.6.7",
4 | "fileTypes": [
5 | "rhai"
6 | ],
7 | "uuid": "1e76f176-ee1c-4331-a781-eb21c0da77cf",
8 | "scopeName": "source.rhai",
9 | "information_for_contributors": [
10 | "aster: galaster@foxmail.com",
11 | "schungx: schungx@live.com"
12 | ],
13 | "patterns": [
14 | {
15 | "include": "#core"
16 | }
17 | ],
18 | "repository": {
19 | "core": {
20 | "patterns": [
21 | {
22 | "include": "#expression"
23 | }
24 | ]
25 | },
26 | "expression": {
27 | "patterns": [
28 | {
29 | "include": "#literal-closure-labels"
30 | },
31 | {
32 | "include": "#literal-labels"
33 | },
34 | {
35 | "include": "#literal-keywords"
36 | },
37 | {
38 | "include": "#support"
39 | },
40 | {
41 | "include": "#literal-function"
42 | },
43 | {
44 | "include": "#literal-closure"
45 | },
46 | {
47 | "include": "#literal-constant"
48 | },
49 | {
50 | "include": "#literal-template-string"
51 | },
52 | {
53 | "include": "#literal-language-variable"
54 | },
55 | {
56 | "include": "#literal-module"
57 | },
58 | {
59 | "include": "#literal-method-call"
60 | },
61 | {
62 | "include": "#literal-function-call"
63 | },
64 | {
65 | "include": "#comments"
66 | },
67 | {
68 | "include": "#brackets"
69 | },
70 | {
71 | "include": "#literal-operators"
72 | },
73 | {
74 | "include": "#literal-namespace"
75 | },
76 | {
77 | "include": "#literal-variable"
78 | },
79 | {
80 | "include": "#literal-punctuation"
81 | }
82 | ]
83 | },
84 | "literal-constant": {
85 | "patterns": [
86 | {
87 | "include": "#literal-number"
88 | },
89 | {
90 | "include": "#literal-string"
91 | },
92 | {
93 | "include": "#literal-language-constant"
94 | }
95 | ]
96 | },
97 | "round-brackets": {
98 | "patterns": [
99 | {
100 | "name": "meta.group.braces.round",
101 | "begin": "\\((?!\\*)",
102 | "beginCaptures": {
103 | "0": {
104 | "name": "meta.brace.round.rhai"
105 | }
106 | },
107 | "end": "(?)\\s*(\\|)(?=\\s*[_a-zA-Z\\|])",
381 | "beginCaptures": {
382 | "1": {
383 | "name": "punctuation.separator.switch.case.rhai"
384 | },
385 | "2": {
386 | "name": "punctuation.definition.parameters.closure.begin.rhai"
387 | }
388 | },
389 | "end": "(\\|)",
390 | "endCaptures": {
391 | "1": {
392 | "name": "punctuation.definition.parameters.closure.end.rhai"
393 | }
394 | },
395 | "patterns": [
396 | {
397 | "include": "#parameters-list"
398 | }
399 | ]
400 | }
401 | ]
402 | },
403 | "literal-closure-labels": {
404 | "patterns": [
405 | {
406 | "name": "meta.function.closure.rhai",
407 | "begin": "(\\b[_a-zA-Z]\\w*)\\s*(\\:)\\s*(\\|)(?=\\s*[_a-zA-Z\\|])",
408 | "beginCaptures": {
409 | "1": {
410 | "name": "string.unquoted.label.rhai entity.name.function.method.rhai"
411 | },
412 | "2": {
413 | "name": "punctuation.separator.key-value.rhai"
414 | },
415 | "3": {
416 | "name": "punctuation.definition.parameters.closure.begin.rhai"
417 | }
418 | },
419 | "end": "(\\|)",
420 | "endCaptures": {
421 | "1": {
422 | "name": "punctuation.definition.parameters.closure.end.rhai"
423 | }
424 | },
425 | "patterns": [
426 | {
427 | "include": "#parameters-list"
428 | }
429 | ]
430 | },
431 | {
432 | "name": "meta.function.closure.rhai",
433 | "begin": "((\\\")((?:[^\"]|\\\\\")*)(\\\"))\\s*(:)\\s*(\\|)(?=\\s*[_a-zA-Z\\|])",
434 | "beginCaptures": {
435 | "1": {
436 | "name": "string.quoted.double.rhai"
437 | },
438 | "2": {
439 | "name": "punctuation.definition.string.begin.rhai"
440 | },
441 | "3": {
442 | "name": "entity.name.function.method.rhai"
443 | },
444 | "4": {
445 | "name": "punctuation.definition.string.end.rhai"
446 | },
447 | "5": {
448 | "name": "punctuation.separator.key-value.rhai"
449 | },
450 | "6": {
451 | "name": "punctuation.definition.parameters.closure.begin.rhai"
452 | }
453 | },
454 | "end": "(\\|)",
455 | "endCaptures": {
456 | "1": {
457 | "name": "punctuation.definition.parameters.closure.end.rhai"
458 | }
459 | },
460 | "patterns": [
461 | {
462 | "include": "#parameters-list"
463 | }
464 | ]
465 | }
466 | ]
467 | },
468 | "literal-function-call": {
469 | "patterns": [
470 | {
471 | "name": "meta.function-call.without-arguments.rhai",
472 | "match": "(?x)\n ([_a-zA-Z]\\w*)(!)?\\s*\n (\\(\\s*\\))",
473 | "captures": {
474 | "1": {
475 | "name": "entity.name.function.rhai"
476 | },
477 | "2": {
478 | "name": "punctuation.function-call.capture.rhai"
479 | },
480 | "3": {
481 | "name": "meta.group.braces.round.function.arguments.rhai"
482 | }
483 | }
484 | },
485 | {
486 | "name": "meta.function-call.with-arguments.rhai",
487 | "match": "(?x)\n ([_a-zA-Z]\\w*)(!)?\\s*\n (?=\\()",
488 | "captures": {
489 | "1": {
490 | "name": "entity.name.function.rhai"
491 | },
492 | "2": {
493 | "name": "punctuation.function-call.capture.rhai"
494 | }
495 | }
496 | }
497 | ]
498 | },
499 | "literal-method-call": {
500 | "patterns": [
501 | {
502 | "name": "meta.function-call.method.without-arguments.rhai",
503 | "match": "(?x)\n (?<=(\\.|\\?\\.))\n \\s*([_a-zA-Z]\\w*)\\s*\n (\\(\\s*\\))",
504 | "captures": {
505 | "1": {
506 | "name": "entity.name.function.rhai"
507 | },
508 | "2": {
509 | "name": "meta.group.braces.round.function.arguments.rhai"
510 | }
511 | }
512 | },
513 | {
514 | "name": "meta.function-call.method.with-arguments.rhai",
515 | "match": "(?x)\n (?<=(\\.|\\?\\.))\n \\s*([_a-zA-Z]\\w*)\\s*\n (?=\\()",
516 | "captures": {
517 | "1": {
518 | "name": "entity.name.function.rhai"
519 | }
520 | }
521 | }
522 | ]
523 | },
524 | "literal-language-variable": {
525 | "patterns": [
526 | {
527 | "name": "variable.language.this.rhai",
528 | "match": "\\bthis\\b"
529 | }
530 | ]
531 | },
532 | "literal-language-constant": {
533 | "patterns": [
534 | {
535 | "name": "constant.language.boolean.true.rhai",
536 | "match": "\\btrue\\b"
537 | },
538 | {
539 | "name": "constant.language.boolean.false.rhai",
540 | "match": "\\bfalse\\b"
541 | }
542 | ]
543 | },
544 | "literal-language-namespace": {
545 | "patterns": [
546 | {
547 | "match": "(?]) # assignment right-to-left both"
610 | },
611 | {
612 | "name": "keyword.operator.assignment.augmented.rhai",
613 | "match": "(?x)\n %= | # assignment right-to-left both\n &= | # assignment right-to-left both\n \\*\\*=| # assignment right-to-left both\n (?>= # assignment right-to-left both"
614 | },
615 | {
616 | "name": "keyword.operator.bitwise.rhai",
617 | "match": "(?x)\n << | # bitwise-shift left-to-right both\n >> | # bitwise-shift left-to-right both\n & | # bitwise-and left-to-right both\n \\^ | # bitwise-xor left-to-right both\n \\| # bitwise-or left-to-right both"
618 | },
619 | {
620 | "name": "keyword.operator.relational.rhai",
621 | "match": "(?x)\n <= | # relational left-to-right both\n >= | # relational left-to-right both\n <(?!-) | # relational left-to-right both\n (? # relational left-to-right both"
622 | },
623 | {
624 | "name": "keyword.operator.comparison.rhai",
625 | "match": "(?x)\n ==(?!=) | # equality left-to-right both\n !=(?!=) # equality left-to-right both"
626 | },
627 | {
628 | "name": "keyword.operator.arithmetic.rhai",
629 | "match": "(?x)\n / | # division left-to-right both\n % | # modulus left-to-right both\n \\*\\* | # power left-to-right both\n \\*(?!\\)) | # multiplication left-to-right both\n \\+(?!\\+) | # addition left-to-right both\n -(?![>-]) # subtraction left-to-right both"
630 | },
631 | {
632 | "name": "keyword.operator.range.exclusive.rhai",
633 | "match": "\\.\\.(?![\\.=])"
634 | },
635 | {
636 | "name": "keyword.operator.range.inclusive.rhai",
637 | "match": "\\.\\.="
638 | },
639 | {
640 | "name": "keyword.operator.accessor.rhai punctuation.accessor.rhai",
641 | "match": "\\.(?!\\.)|\\?\\."
642 | },
643 | {
644 | "name": "punctuation.separator.switch.case.rhai",
645 | "match": "=>"
646 | },
647 | {
648 | "name": "invalid.illegal.operator.rhai",
649 | "match": "(\\(\\*|\\*\\)|\\+\\+|--|\\.\\.\\.+|~|#(?!{)|@|\\?|\\$(?!{)|->|<-|===|!==|\\:=|\\:\\:<)"
650 | }
651 | ]
652 | },
653 | "literal-labels": {
654 | "patterns": [
655 | {
656 | "begin": "(?x)\n (?-
164 | (?x)
165 | (?:\b(private)\s+)?
166 | \s*(fn)
167 | \s*([_a-zA-Z]\w*)\s*
168 | beginCaptures:
169 | '1': {name: storage.modifier.rhai}
170 | '2': {name: storage.type.function.rhai}
171 | '3': {name: entity.name.function.rhai}
172 | end: (?<=\))
173 | patterns:
174 | - include: '#parameters-list'
175 |
176 | - name: keyword.other.function.rhai
177 | match: \b(fn)\b
178 |
179 | - name: keyword.other.modifier.rhai
180 | match: \b(private)\b
181 |
182 | literal-closure:
183 | patterns:
184 | # e.g. |args| { }
185 | - name: meta.function.closure.rhai
186 | begin: (\|)(?=\s*[_a-zA-Z\|])
187 | beginCaptures:
188 | '1': {name: punctuation.definition.parameters.closure.begin.rhai}
189 | end: (\|)
190 | endCaptures:
191 | '1': {name: punctuation.definition.parameters.closure.end.rhai}
192 | patterns:
193 | - include: '#parameters-list'
194 |
195 | # e.g. play = |args| { }
196 | - name: meta.function.closure.rhai
197 | begin: (\b[_a-zA-Z]\w*)\s*(=)\s*(\|)(?=\s*[_a-zA-Z\|])
198 | beginCaptures:
199 | '1': {name: entity.name.function.closure.rhai}
200 | '2': {name: keyword.operator.assignment.rhai}
201 | '3': {name: punctuation.definition.parameters.closure.begin.rhai}
202 | end: (\|)
203 | endCaptures:
204 | '1': {name: punctuation.definition.parameters.closure.end.rhai}
205 | patterns:
206 | - include: '#parameters-list'
207 |
208 | # e.g. => |args| { }
209 | - name: meta.function.closure.rhai
210 | begin: (=>)\s*(\|)(?=\s*[_a-zA-Z\|])
211 | beginCaptures:
212 | '1': {name: punctuation.separator.switch.case.rhai}
213 | '2': {name: punctuation.definition.parameters.closure.begin.rhai}
214 | end: (\|)
215 | endCaptures:
216 | '1': {name: punctuation.definition.parameters.closure.end.rhai}
217 | patterns:
218 | - include: '#parameters-list'
219 |
220 | literal-closure-labels:
221 | patterns:
222 | # e.g. play: |args| { }
223 | - name: meta.function.closure.rhai
224 | begin: (\b[_a-zA-Z]\w*)\s*(\:)\s*(\|)(?=\s*[_a-zA-Z\|])
225 | beginCaptures:
226 | '1': {name: string.unquoted.label.rhai entity.name.function.method.rhai}
227 | '2': {name: punctuation.separator.key-value.rhai}
228 | '3': {name: punctuation.definition.parameters.closure.begin.rhai}
229 | end: (\|)
230 | endCaptures:
231 | '1': {name: punctuation.definition.parameters.closure.end.rhai}
232 | patterns:
233 | - include: '#parameters-list'
234 |
235 | # e.g. "play": |args| { }
236 | - name: meta.function.closure.rhai
237 | begin: ((\")((?:[^"]|\\")*)(\"))\s*(:)\s*(\|)(?=\s*[_a-zA-Z\|])
238 | beginCaptures:
239 | '1': {name: string.quoted.double.rhai}
240 | '2': {name: punctuation.definition.string.begin.rhai}
241 | '3': {name: entity.name.function.method.rhai}
242 | '4': {name: punctuation.definition.string.end.rhai}
243 | '5': {name: punctuation.separator.key-value.rhai}
244 | '6': {name: punctuation.definition.parameters.closure.begin.rhai}
245 | end: (\|)
246 | endCaptures:
247 | '1': {name: punctuation.definition.parameters.closure.end.rhai}
248 | patterns:
249 | - include: '#parameters-list'
250 |
251 | literal-function-call:
252 | patterns:
253 | - name: meta.function-call.without-arguments.rhai
254 | match: >-
255 | (?x)
256 | ([_a-zA-Z]\w*)(!)?\s*
257 | (\(\s*\))
258 | captures:
259 | '1': {name: entity.name.function.rhai}
260 | '2': {name: punctuation.function-call.capture.rhai}
261 | '3': {name: meta.group.braces.round.function.arguments.rhai}
262 |
263 | - name: meta.function-call.with-arguments.rhai
264 | match: >-
265 | (?x)
266 | ([_a-zA-Z]\w*)(!)?\s*
267 | (?=\()
268 | captures:
269 | '1': {name: entity.name.function.rhai}
270 | '2': {name: punctuation.function-call.capture.rhai}
271 |
272 | literal-method-call:
273 | patterns:
274 | - name: meta.function-call.method.without-arguments.rhai
275 | match: >-
276 | (?x)
277 | (?<=(\.|\?\.))
278 | \s*([_a-zA-Z]\w*)\s*
279 | (\(\s*\))
280 | captures:
281 | '1': {name: entity.name.function.rhai}
282 | '2': {name: meta.group.braces.round.function.arguments.rhai}
283 |
284 | - name: meta.function-call.method.with-arguments.rhai
285 | match: >-
286 | (?x)
287 | (?<=(\.|\?\.))
288 | \s*([_a-zA-Z]\w*)\s*
289 | (?=\()
290 | captures:
291 | '1': {name: entity.name.function.rhai}
292 |
293 | literal-language-variable:
294 | patterns:
295 | - name: variable.language.this.rhai
296 | match: \bthis\b
297 |
298 | literal-language-constant:
299 | patterns:
300 | - name: constant.language.boolean.true.rhai
301 | match: \btrue\b
302 |
303 | - name: constant.language.boolean.false.rhai
304 | match: \bfalse\b
305 |
306 | literal-language-namespace:
307 | patterns:
308 | - match: (?-
339 | (?x)
340 | !(?!=)| # logical-not right-to-left right
341 | && | # logical-and left-to-right both
342 | \|\| # logical-or left-to-right both
343 | - name: keyword.operator.containment.rhai
344 | match: >-
345 | (?x)
346 | \bin\b | # in left-to-right both
347 | \B!in\b # not-in left-to-right both
348 | - name: keyword.operator.coalesce.rhai
349 | match: >-
350 | (?x)
351 | \?\? # null-coalesce left-to-right both
352 | - name: keyword.operator.assignment.rhai
353 | match: >-
354 | (?x)
355 | =(?![=>]) # assignment right-to-left both
356 | - name: keyword.operator.assignment.augmented.rhai
357 | match: >-
358 | (?x)
359 | %= | # assignment right-to-left both
360 | &= | # assignment right-to-left both
361 | \*\*=| # assignment right-to-left both
362 | (?>= # assignment right-to-left both
370 | - name: keyword.operator.bitwise.rhai
371 | match: >-
372 | (?x)
373 | << | # bitwise-shift left-to-right both
374 | >> | # bitwise-shift left-to-right both
375 | & | # bitwise-and left-to-right both
376 | \^ | # bitwise-xor left-to-right both
377 | \| # bitwise-or left-to-right both
378 | - name: keyword.operator.relational.rhai
379 | match: >-
380 | (?x)
381 | <= | # relational left-to-right both
382 | >= | # relational left-to-right both
383 | <(?!-) | # relational left-to-right both
384 | (? # relational left-to-right both
385 | - name: keyword.operator.comparison.rhai
386 | match: >-
387 | (?x)
388 | ==(?!=) | # equality left-to-right both
389 | !=(?!=) # equality left-to-right both
390 | - name: keyword.operator.arithmetic.rhai
391 | match: >-
392 | (?x)
393 | / | # division left-to-right both
394 | % | # modulus left-to-right both
395 | \*\* | # power left-to-right both
396 | \*(?!\)) | # multiplication left-to-right both
397 | \+(?!\+) | # addition left-to-right both
398 | -(?![>-]) # subtraction left-to-right both
399 | - name: keyword.operator.range.exclusive.rhai
400 | match: \.\.(?![\.=])
401 | - name: keyword.operator.range.inclusive.rhai
402 | match: \.\.=
403 | - name: keyword.operator.accessor.rhai punctuation.accessor.rhai
404 | match: \.(?!\.)|\?\.
405 | - name: punctuation.separator.switch.case.rhai
406 | match: =>
407 | - name: invalid.illegal.operator.rhai
408 | match: (\(\*|\*\)|\+\+|--|\.\.\.+|~|#(?!{)|@|\?|\$(?!{)|->|<-|===|!==|\:=|\:\:<)
409 |
410 | literal-labels:
411 | patterns:
412 | - begin: >-
413 | (?x)
414 | (?-
431 | (?xi)
432 | (?:
433 | \b0b[0-1][_0-1]*| # binary
434 | \b0o[0-7][_0-7]*| # octal
435 | \b0x[\da-f][_\da-f]*| # hex
436 | (\B[+\-])?\b\d[_\d]*\.\d[_\d]*(e[+\-]?\d[_\d]*)?| # e.g. 999.999, 999.99e+123
437 | (\B[+\-])?\b\d[_\d]*\.(?!\.)\B| # e.g. 999.
438 | (\B[+\-])?\b\d[_\d]*(e[+\-]?\d[_\d]*)? # e.g. 999, 999e+123
439 | )
440 |
441 | literal-punctuation:
442 | patterns:
443 | - name: punctuation.terminator.statement.rhai
444 | match: \;
445 |
446 | - name: meta.delimiter.comma.rhai
447 | match: \,
448 |
449 | literal-template-string:
450 | patterns:
451 | - name: string.interpolated.rhai
452 | begin: '`'
453 | beginCaptures:
454 | '0': {name: punctuation.definition.string.begin.rhai}
455 | end: '`'
456 | endCaptures:
457 | '0': {name: punctuation.definition.string.end.rhai}
458 | patterns:
459 | - include: '#string-content'
460 | - name: meta.interpolation.rhai
461 | begin: \${
462 | beginCaptures:
463 | '0': {name: punctuation.section.interpolation.begin.rhai}
464 | end: '}'
465 | endCaptures:
466 | '0': {name: punctuation.section.interpolation.end.rhai}
467 | patterns:
468 | - include: '#expression'
469 |
470 | literal-string:
471 | patterns:
472 | - name: string.quoted.single.rhai
473 | match: ('([^'\\]|\\([tnr'\\]|x\h{2}|u\h{4}|U\h{8}))')
474 | patterns:
475 | - match: \\([tnr'\\]|x\h{2}|u\h{4}|U\h{8})
476 | name: constant.character.escape.rhai
477 |
478 | - name: string.quoted.double.rhai
479 | begin: (")
480 | beginCaptures:
481 | '1': {name: punctuation.definition.string.begin.rhai}
482 | end: (")
483 | endCaptures:
484 | '1': {name: punctuation.definition.string.end.rhai}
485 | patterns:
486 | - include: '#string-content'
487 | - name: invalid.illegal.newline.rhai
488 | match: (?` \n\t",
67 | "surroundingPairs": [
68 | [
69 | "{",
70 | "}"
71 | ],
72 | [
73 | "[",
74 | "]"
75 | ],
76 | [
77 | "(",
78 | ")"
79 | ],
80 | [
81 | "'",
82 | "'"
83 | ],
84 | [
85 | "\"",
86 | "\""
87 | ],
88 | [
89 | "`",
90 | "`"
91 | ]
92 | ],
93 | "folding": {
94 | "markers": {
95 | "start": "^\\s*//\\s*#?region\\b",
96 | "end": "^\\s*//\\s*#?endregion\\b"
97 | }
98 | },
99 | "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)",
100 | "indentationRules": {
101 | "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
102 | "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\}\\]].*$"
103 | }
104 | }
--------------------------------------------------------------------------------
/syntax/rhai.markdown.json:
--------------------------------------------------------------------------------
1 | {
2 | "scopeName": "markdown.rhai.codeblock",
3 | "injectionSelector": "L:text.html.markdown",
4 | "patterns": [
5 | {
6 | "name": "markup.fenced_code.block.rhai",
7 | "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(rhai)((\\s+|:|\\{)[^`~]*)?$)",
8 | "beginCaptures": {
9 | "3": {
10 | "name": "punctuation.definition.markdown"
11 | },
12 | "4": {
13 | "name": "fenced_code.block.language.markdown"
14 | },
15 | "5": {
16 | "name": "fenced_code.block.language.attributes.markdown"
17 | }
18 | },
19 | "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
20 | "endCaptures": {
21 | "3": {
22 | "name": "punctuation.definition.markdown"
23 | }
24 | },
25 | "patterns": [
26 | {
27 | "begin": "(^|\\G)(\\s*)(.*)",
28 | "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)",
29 | "contentName": "meta.embedded.block.rhai",
30 | "patterns": [
31 | {
32 | "include": "source.rhai"
33 | }
34 | ]
35 | }
36 | ]
37 | }
38 | ]
39 | }
--------------------------------------------------------------------------------
/syntax/rhai.tmLanguage.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Rhai",
3 | "version": "v0.6.7",
4 | "fileTypes": [
5 | "rhai"
6 | ],
7 | "uuid": "1e76f176-ee1c-4331-a781-eb21c0da77cf",
8 | "scopeName": "source.rhai",
9 | "information_for_contributors": [
10 | "aster: galaster@foxmail.com",
11 | "schungx: schungx@live.com"
12 | ],
13 | "patterns": [
14 | {
15 | "include": "#core"
16 | }
17 | ],
18 | "repository": {
19 | "core": {
20 | "patterns": [
21 | {
22 | "include": "#expression"
23 | }
24 | ]
25 | },
26 | "expression": {
27 | "patterns": [
28 | {
29 | "include": "#literal-closure-labels"
30 | },
31 | {
32 | "include": "#literal-labels"
33 | },
34 | {
35 | "include": "#literal-keywords"
36 | },
37 | {
38 | "include": "#support"
39 | },
40 | {
41 | "include": "#literal-function"
42 | },
43 | {
44 | "include": "#literal-closure"
45 | },
46 | {
47 | "include": "#literal-constant"
48 | },
49 | {
50 | "include": "#literal-template-string"
51 | },
52 | {
53 | "include": "#literal-language-variable"
54 | },
55 | {
56 | "include": "#literal-module"
57 | },
58 | {
59 | "include": "#literal-method-call"
60 | },
61 | {
62 | "include": "#literal-function-call"
63 | },
64 | {
65 | "include": "#comments"
66 | },
67 | {
68 | "include": "#brackets"
69 | },
70 | {
71 | "include": "#literal-operators"
72 | },
73 | {
74 | "include": "#literal-namespace"
75 | },
76 | {
77 | "include": "#literal-variable"
78 | },
79 | {
80 | "include": "#literal-punctuation"
81 | }
82 | ]
83 | },
84 | "literal-constant": {
85 | "patterns": [
86 | {
87 | "include": "#literal-number"
88 | },
89 | {
90 | "include": "#literal-string"
91 | },
92 | {
93 | "include": "#literal-language-constant"
94 | }
95 | ]
96 | },
97 | "round-brackets": {
98 | "patterns": [
99 | {
100 | "name": "meta.group.braces.round",
101 | "begin": "\\((?!\\*)",
102 | "beginCaptures": {
103 | "0": {
104 | "name": "meta.brace.round.rhai"
105 | }
106 | },
107 | "end": "(?)\\s*(\\|)(?=\\s*[_a-zA-Z\\|])",
381 | "beginCaptures": {
382 | "1": {
383 | "name": "punctuation.separator.switch.case.rhai"
384 | },
385 | "2": {
386 | "name": "punctuation.definition.parameters.closure.begin.rhai"
387 | }
388 | },
389 | "end": "(\\|)",
390 | "endCaptures": {
391 | "1": {
392 | "name": "punctuation.definition.parameters.closure.end.rhai"
393 | }
394 | },
395 | "patterns": [
396 | {
397 | "include": "#parameters-list"
398 | }
399 | ]
400 | }
401 | ]
402 | },
403 | "literal-closure-labels": {
404 | "patterns": [
405 | {
406 | "name": "meta.function.closure.rhai",
407 | "begin": "(\\b[_a-zA-Z]\\w*)\\s*(\\:)\\s*(\\|)(?=\\s*[_a-zA-Z\\|])",
408 | "beginCaptures": {
409 | "1": {
410 | "name": "string.unquoted.label.rhai entity.name.function.method.rhai"
411 | },
412 | "2": {
413 | "name": "punctuation.separator.key-value.rhai"
414 | },
415 | "3": {
416 | "name": "punctuation.definition.parameters.closure.begin.rhai"
417 | }
418 | },
419 | "end": "(\\|)",
420 | "endCaptures": {
421 | "1": {
422 | "name": "punctuation.definition.parameters.closure.end.rhai"
423 | }
424 | },
425 | "patterns": [
426 | {
427 | "include": "#parameters-list"
428 | }
429 | ]
430 | },
431 | {
432 | "name": "meta.function.closure.rhai",
433 | "begin": "((\\\")((?:[^\"]|\\\\\")*)(\\\"))\\s*(:)\\s*(\\|)(?=\\s*[_a-zA-Z\\|])",
434 | "beginCaptures": {
435 | "1": {
436 | "name": "string.quoted.double.rhai"
437 | },
438 | "2": {
439 | "name": "punctuation.definition.string.begin.rhai"
440 | },
441 | "3": {
442 | "name": "entity.name.function.method.rhai"
443 | },
444 | "4": {
445 | "name": "punctuation.definition.string.end.rhai"
446 | },
447 | "5": {
448 | "name": "punctuation.separator.key-value.rhai"
449 | },
450 | "6": {
451 | "name": "punctuation.definition.parameters.closure.begin.rhai"
452 | }
453 | },
454 | "end": "(\\|)",
455 | "endCaptures": {
456 | "1": {
457 | "name": "punctuation.definition.parameters.closure.end.rhai"
458 | }
459 | },
460 | "patterns": [
461 | {
462 | "include": "#parameters-list"
463 | }
464 | ]
465 | }
466 | ]
467 | },
468 | "literal-function-call": {
469 | "patterns": [
470 | {
471 | "name": "meta.function-call.without-arguments.rhai",
472 | "match": "(?x)\n ([_a-zA-Z]\\w*)(!)?\\s*\n (\\(\\s*\\))",
473 | "captures": {
474 | "1": {
475 | "name": "entity.name.function.rhai"
476 | },
477 | "2": {
478 | "name": "punctuation.function-call.capture.rhai"
479 | },
480 | "3": {
481 | "name": "meta.group.braces.round.function.arguments.rhai"
482 | }
483 | }
484 | },
485 | {
486 | "name": "meta.function-call.with-arguments.rhai",
487 | "match": "(?x)\n ([_a-zA-Z]\\w*)(!)?\\s*\n (?=\\()",
488 | "captures": {
489 | "1": {
490 | "name": "entity.name.function.rhai"
491 | },
492 | "2": {
493 | "name": "punctuation.function-call.capture.rhai"
494 | }
495 | }
496 | }
497 | ]
498 | },
499 | "literal-method-call": {
500 | "patterns": [
501 | {
502 | "name": "meta.function-call.method.without-arguments.rhai",
503 | "match": "(?x)\n (?<=(\\.|\\?\\.))\n \\s*([_a-zA-Z]\\w*)\\s*\n (\\(\\s*\\))",
504 | "captures": {
505 | "1": {
506 | "name": "entity.name.function.rhai"
507 | },
508 | "2": {
509 | "name": "meta.group.braces.round.function.arguments.rhai"
510 | }
511 | }
512 | },
513 | {
514 | "name": "meta.function-call.method.with-arguments.rhai",
515 | "match": "(?x)\n (?<=(\\.|\\?\\.))\n \\s*([_a-zA-Z]\\w*)\\s*\n (?=\\()",
516 | "captures": {
517 | "1": {
518 | "name": "entity.name.function.rhai"
519 | }
520 | }
521 | }
522 | ]
523 | },
524 | "literal-language-variable": {
525 | "patterns": [
526 | {
527 | "name": "variable.language.this.rhai",
528 | "match": "\\bthis\\b"
529 | }
530 | ]
531 | },
532 | "literal-language-constant": {
533 | "patterns": [
534 | {
535 | "name": "constant.language.boolean.true.rhai",
536 | "match": "\\btrue\\b"
537 | },
538 | {
539 | "name": "constant.language.boolean.false.rhai",
540 | "match": "\\bfalse\\b"
541 | }
542 | ]
543 | },
544 | "literal-language-namespace": {
545 | "patterns": [
546 | {
547 | "match": "(?]) # assignment right-to-left both"
610 | },
611 | {
612 | "name": "keyword.operator.assignment.augmented.rhai",
613 | "match": "(?x)\n %= | # assignment right-to-left both\n &= | # assignment right-to-left both\n \\*\\*=| # assignment right-to-left both\n (?>= # assignment right-to-left both"
614 | },
615 | {
616 | "name": "keyword.operator.bitwise.rhai",
617 | "match": "(?x)\n << | # bitwise-shift left-to-right both\n >> | # bitwise-shift left-to-right both\n & | # bitwise-and left-to-right both\n \\^ | # bitwise-xor left-to-right both\n \\| # bitwise-or left-to-right both"
618 | },
619 | {
620 | "name": "keyword.operator.relational.rhai",
621 | "match": "(?x)\n <= | # relational left-to-right both\n >= | # relational left-to-right both\n <(?!-) | # relational left-to-right both\n (? # relational left-to-right both"
622 | },
623 | {
624 | "name": "keyword.operator.comparison.rhai",
625 | "match": "(?x)\n ==(?!=) | # equality left-to-right both\n !=(?!=) # equality left-to-right both"
626 | },
627 | {
628 | "name": "keyword.operator.arithmetic.rhai",
629 | "match": "(?x)\n / | # division left-to-right both\n % | # modulus left-to-right both\n \\*\\* | # power left-to-right both\n \\*(?!\\)) | # multiplication left-to-right both\n \\+(?!\\+) | # addition left-to-right both\n -(?![>-]) # subtraction left-to-right both"
630 | },
631 | {
632 | "name": "keyword.operator.range.exclusive.rhai",
633 | "match": "\\.\\.(?![\\.=])"
634 | },
635 | {
636 | "name": "keyword.operator.range.inclusive.rhai",
637 | "match": "\\.\\.="
638 | },
639 | {
640 | "name": "keyword.operator.accessor.rhai punctuation.accessor.rhai",
641 | "match": "\\.(?!\\.)|\\?\\."
642 | },
643 | {
644 | "name": "punctuation.separator.switch.case.rhai",
645 | "match": "=>"
646 | },
647 | {
648 | "name": "invalid.illegal.operator.rhai",
649 | "match": "(\\(\\*|\\*\\)|\\+\\+|--|\\.\\.\\.+|~|#(?!{)|@|\\?|\\$(?!{)|->|<-|===|!==|\\:=|\\:\\:<)"
650 | }
651 | ]
652 | },
653 | "literal-labels": {
654 | "patterns": [
655 | {
656 | "begin": "(?x)\n (? 100 { continue; }
9 |
10 | print(`(${i}, ${j}) = (${a}, ${b})`);
11 | }
12 |
13 | if a == 3 { break; }
14 | }
15 | //print(a); // <- if you uncomment this line, the script will fail to compile
16 | // because 'a' is not defined here
17 |
18 | for i in range(5, 0, -1) { // runs from 5 down to 1
19 | print(i);
20 | }
21 |
--------------------------------------------------------------------------------
/test/for2.rhai:
--------------------------------------------------------------------------------
1 | // This script runs for-loops
2 |
3 | const MAX = 1_000_000;
4 |
5 | print(`Iterating an array with ${MAX} items...`);
6 |
7 | print("Ready... Go!");
8 |
9 | let now = timestamp();
10 |
11 | let list = [];
12 |
13 | // Loop over range
14 | for i in 0..MAX {
15 | list.push(i);
16 | }
17 |
18 | print(`Time = ${now.elapsed} seconds...`);
19 |
20 | let sum = 0;
21 |
22 | // Loop over array
23 | for i in list {
24 | sum += i;
25 | }
26 |
27 | print(`Sum = ${sum}`);
28 | print(`Finished. Total run time = ${now.elapsed} seconds.`);
29 |
--------------------------------------------------------------------------------
/test/for3.rhai:
--------------------------------------------------------------------------------
1 | // This script runs for-loops with closures.
2 |
3 | const MAX = 100;
4 | const CHECK = ((MAX - 1) ** 2) * MAX;
5 |
6 | print("Ready... Go!");
7 |
8 | let now = timestamp();
9 |
10 | print(`Creating ${MAX} closures...`);
11 |
12 | let list = [];
13 |
14 | // Loop over range
15 | for i in 0..MAX {
16 | list.push(|| i ** 2);
17 | }
18 |
19 | print(`Time = ${now.elapsed} seconds...`);
20 | print(`Summing ${MAX} closures...`);
21 |
22 | let sum = 0;
23 |
24 | // Loop over array
25 | for f in list {
26 | sum += f.call();
27 | }
28 |
29 | print(`Sum = ${sum} (should be ${CHECK})`);
30 | print(`Finished. Total run time = ${now.elapsed} seconds.`);
31 |
--------------------------------------------------------------------------------
/test/function_decl1.rhai:
--------------------------------------------------------------------------------
1 | // This script defines a function and calls it.
2 |
3 | fn call_me() {
4 | return 3;
5 | }
6 |
7 | let result = call_me();
8 |
9 | print(`call_me() should be 3: ${result}`);
10 |
--------------------------------------------------------------------------------
/test/function_decl2.rhai:
--------------------------------------------------------------------------------
1 | // This script defines a function with two parameters and local variables.
2 |
3 | let a = 3;
4 |
5 | fn add(a, b) {
6 | a = 42; // notice that 'a' is passed by value
7 | a + b; // notice that the last value is returned even if terminated by a semicolon
8 | }
9 |
10 | let result = add(a, 4);
11 |
12 | print(`add(a, 4) should be 46: ${result}`);
13 |
14 | print(`a should still be 3: ${a}`); // prints 3: 'a' is never changed
15 |
--------------------------------------------------------------------------------
/test/function_decl3.rhai:
--------------------------------------------------------------------------------
1 | // This script defines a function with many parameters.
2 | //
3 |
4 | const KEY = 38;
5 |
6 | fn f(a, b, c, d, e, f) {
7 | let x = global::KEY; // <- access global module
8 | a - b * c - d * e - f + x
9 | }
10 |
11 | let result = f(100, 5, 2, 9, 6, 32);
12 |
13 | print(`result should be 42: ${result}`);
14 |
--------------------------------------------------------------------------------
/test/function_decl4.rhai:
--------------------------------------------------------------------------------
1 | // This script defines a function that acts as a method.
2 |
3 | // Use 'this' to refer to the object of a method call
4 | fn action(x, y) {
5 | this = this.abs() + x * y; // 'this' can be modified
6 | }
7 |
8 | let obj = -40;
9 |
10 | obj.action(1, 2); // call 'action' as method
11 |
12 | print(`obj should now be 42: ${obj}`);
13 |
--------------------------------------------------------------------------------
/test/if1.rhai:
--------------------------------------------------------------------------------
1 | // This script runs if statements.
2 |
3 | let a = 42;
4 | let b = 123;
5 | let x = 999;
6 |
7 | if a > b {
8 | print("Oops! a > b");
9 | } else if a < b {
10 | print("a < b, x should be 0");
11 |
12 | let x = 0; // <- this 'x' shadows the global 'x'
13 | print(x); // should print 0
14 | } else {
15 | print("Oops! a == b");
16 | }
17 |
--------------------------------------------------------------------------------
/test/if2.rhai:
--------------------------------------------------------------------------------
1 | // This script runs an if expression.
2 |
3 | let a = 42;
4 | let b = 123;
5 |
6 | let x = if a <= b { // <- if-expression
7 | b - a
8 | } else {
9 | a - b
10 | } * 10;
11 |
12 | print(`x should be 810: ${x}`);
13 |
--------------------------------------------------------------------------------
/test/loop.rhai:
--------------------------------------------------------------------------------
1 | // This script runs an infinite loop, ending it with a break statement.
2 |
3 | let x = 10;
4 |
5 | // simulate do..while using loop
6 | loop {
7 | print(x);
8 |
9 | x -= 1;
10 |
11 | if x <= 0 { break; }
12 | }
13 |
14 | export x as foo;
15 |
--------------------------------------------------------------------------------
/test/mat_mul.rhai:
--------------------------------------------------------------------------------
1 | // This script simulates multi-dimensional matrix calculations.
2 |
3 | const SIZE = 50;
4 |
5 | fn new_mat(x, y) {
6 | let row = [];
7 | row.pad(y, 0.0);
8 |
9 | let matrix = [];
10 | matrix.pad(x, row);
11 |
12 | matrix
13 | }
14 |
15 | fn mat_gen() {
16 | const n = global::SIZE;
17 | const tmp = 1.0 / n / n;
18 | let m = new_mat(n, n);
19 |
20 | for i in 0..n {
21 | for j in 0..n {
22 | m[i][j] = tmp * (i - j) * (i + j);
23 | }
24 | }
25 |
26 | m
27 | }
28 |
29 | fn mat_mul(a, b) {
30 | let b2 = new_mat(a[0].len, b[0].len);
31 |
32 | for i in 0..a[0].len {
33 | for j in 0..b[0].len {
34 | b2[j][i] = b[i][j];
35 | }
36 | }
37 |
38 | let c = new_mat(a.len, b[0].len);
39 |
40 | for i in 0..c.len {
41 | for j in 0..c[i].len {
42 | c[i][j] = 0.0;
43 |
44 | for z in 0..a[i].len {
45 | c[i][j] += a[i][z] * b2[j][z];
46 | }
47 | }
48 | }
49 |
50 | c
51 | }
52 |
53 | const now = timestamp();
54 |
55 | const a = mat_gen();
56 | const b = mat_gen();
57 | const c = mat_mul(a, b);
58 |
59 | /*
60 | for i in 0..SIZE) {
61 | print(c[i]);
62 | }
63 | */
64 |
65 | print(`Finished. Run time = ${now.elapsed} seconds.`);
66 |
--------------------------------------------------------------------------------
/test/module.rhai:
--------------------------------------------------------------------------------
1 | // This script imports an external script as a module.
2 |
3 | import "loop" as x;
4 |
5 | print(`Module test! foo = ${x::foo}`);
6 |
--------------------------------------------------------------------------------
/test/oop.rhai:
--------------------------------------------------------------------------------
1 | // This script simulates object-oriented programming (OOP) techniques using closures.
2 |
3 | // External variable that will be captured.
4 | let last_value = ();
5 |
6 | // Define object
7 | let obj1 = #{
8 | _data: 42, // data field
9 | get_data: || this._data, // property getter
10 | action: || print(`Data=${this._data}`), // method
11 | update: |x| { // property setter
12 | this._data = x;
13 | last_value = this._data; // capture 'last_value'
14 | this.action();
15 | }
16 | };
17 |
18 | if obj1.get_data() > 0 { // property access
19 | obj1.update(123); // call method
20 | } else {
21 | print("we have a problem here");
22 | }
23 |
24 | // Define another object based on the first object
25 | let obj2 = #{
26 | _data: 0, // data field - new value
27 | update: |x| { // property setter - another function
28 | this._data = x * 2;
29 | last_value = this._data; // capture 'last_value'
30 | this.action();
31 | }
32 | };
33 | obj2.fill_with(obj1); // add all other fields from obj1
34 |
35 | if obj2.get_data() > 0 { // property access
36 | print("we have another problem here");
37 | } else {
38 | obj2.update(42); // call method
39 | }
40 |
41 | print(`Should be 84: ${last_value}`);
42 |
--------------------------------------------------------------------------------
/test/op1.rhai:
--------------------------------------------------------------------------------
1 | // This script runs a single expression.
2 |
3 | print("The result should be 46:");
4 |
5 | print(34 + 12);
6 |
--------------------------------------------------------------------------------
/test/op2.rhai:
--------------------------------------------------------------------------------
1 | // This script runs a complex expression.
2 |
3 | print("The result should be 182:");
4 |
5 | let x = 12 + 34 * 5;
6 |
7 | print(x);
8 |
--------------------------------------------------------------------------------
/test/op3.rhai:
--------------------------------------------------------------------------------
1 | // This script runs a complex expression.
2 |
3 | print("The result should be 230:");
4 |
5 | let x = (12 + 34) * 5;
6 |
7 | print(x);
8 |
--------------------------------------------------------------------------------
/test/primes.rhai:
--------------------------------------------------------------------------------
1 | // This script uses the Sieve of Eratosthenes to calculate prime numbers.
2 |
3 | let now = timestamp();
4 |
5 | const MAX_NUMBER_TO_CHECK = 1_000_000; // 9592 primes <= 100000
6 |
7 | let prime_mask = [];
8 | prime_mask.pad(MAX_NUMBER_TO_CHECK + 1, true);
9 |
10 | prime_mask[0] = false;
11 | prime_mask[1] = false;
12 |
13 | let total_primes_found = 0;
14 |
15 | for p in 2..=MAX_NUMBER_TO_CHECK {
16 | if !prime_mask[p] { continue; }
17 |
18 | //print(p);
19 |
20 | total_primes_found += 1;
21 |
22 | for i in range(2 * p, MAX_NUMBER_TO_CHECK + 1, p) {
23 | prime_mask[i] = false;
24 | }
25 | }
26 |
27 | print(`Total ${total_primes_found} primes <= ${MAX_NUMBER_TO_CHECK}`);
28 | print(`Run time = ${now.elapsed} seconds.`);
29 |
30 | if total_primes_found != 78_498 {
31 | print("The answer is WRONG! Should be 78,498!");
32 | }
33 |
--------------------------------------------------------------------------------
/test/speed_test.rhai:
--------------------------------------------------------------------------------
1 | // This script runs 1 million iterations to test the speed of the scripting engine.
2 |
3 | let now = timestamp();
4 | let x = 1_000_000;
5 |
6 | print("Ready... Go!");
7 |
8 | while x > 0 {
9 | x -= 1;
10 | }
11 |
12 | print(`Finished. Run time = ${now.elapsed} seconds.`);
13 |
--------------------------------------------------------------------------------
/test/string.rhai:
--------------------------------------------------------------------------------
1 | // This script tests string operations.
2 |
3 | print("hello");
4 | print("this\nis \\ nice"); // escape sequences
5 | print("0x40 hex is \x40"); // hex escape sequence
6 | print("Unicode fun: \u2764"); // Unicode escape sequence
7 | print("more fun: \U0001F603"); // Unicode escape sequence
8 | print("foo" + " " + "bar"); // string building using strings
9 | print("foo" < "bar"); // string comparison
10 | print("foo" >= "bar"); // string comparison
11 | print("the answer is " + 42); // string building using non-string types
12 |
13 | let s = "\u2764 hello, world! \U0001F603"; // string variable
14 | print(`length=${s.len}`); // should be 17
15 |
16 | s[s.len-3] = '?'; // change the string
17 | print(`Question: ${s}`); // should print 'Question: hello, world?'
18 |
19 | // Line continuation:
20 | let s = "This is a long \
21 | string constructed using \
22 | line continuation";
23 |
24 | // String interpolation
25 | print(`One string: ${s}`);
26 |
27 | // Multi-line literal string:
28 | let s = `
29 | \U0001F603 This is a multi-line
30 | "string" with \t\x20\r\n
31 | made using multi-line literal
32 | string syntax.
33 | `;
34 |
35 | print(s);
36 |
37 | // Interpolation
38 | let s = `This is interpolation ${
39 | let x = `within ${let y = "yet another level \
40 | of interpolation!"; y} interpolation`;
41 | x
42 | } within literal string.`;
43 |
44 | print(s);
45 |
46 | print(">>> END <<<");
47 |
--------------------------------------------------------------------------------
/test/strings_map.rhai:
--------------------------------------------------------------------------------
1 | // This script tests object maps and strings.
2 |
3 | print("Ready... Go!");
4 |
5 | let now = timestamp();
6 |
7 | let adverbs = [ "moderately", "really", "slightly", "very" ];
8 |
9 | let adjectives = [
10 | "abandoned", "able", "absolute", "academic", "acceptable", "acclaimed",
11 | "accomplished", "accurate", "aching", "acidic", "acrobatic", "active",
12 | "actual", "adept", "admirable", "admired", "adolescent", "adorable", "adored",
13 | "advanced", "adventurous", "affectionate", "afraid", "aged", "aggravating",
14 | "aggressive", "agile", "agitated", "agonizing", "agreeable", "ajar",
15 | "alarmed", "alarming", "alert", "alienated", "alive", "all", "altruistic",
16 | "amazing", "ambitious", "ample", "amused", "amusing", "anchored", "ancient",
17 | "angelic", "angry", "anguished", "animated", "annual", "another", "antique",
18 | "anxious", "any", "apprehensive", "appropriate", "apt", "arctic", "arid",
19 | "aromatic", "artistic", "ashamed", "assured", "astonishing", "athletic",
20 | "attached", "attentive", "attractive", "austere", "authentic", "authorized",
21 | "automatic", "avaricious", "average", "aware", "awesome", "awful", "awkward",
22 | "babyish", "back", "bad", "baggy", "bare", "barren", "basic", "beautiful",
23 | "belated", "beloved", "beneficial", "best", "better", "bewitched", "big",
24 | "big-hearted", "biodegradable", "bite-sized", "bitter", "black",
25 | "black-and-white", "bland", "blank", "blaring", "bleak", "blind", "blissful",
26 | "blond", "blue", "blushing", "bogus", "boiling", "bold", "bony", "boring",
27 | "bossy", "both", "bouncy", "bountiful", "bowed", "brave", "breakable",
28 | "brief", "bright", "brilliant", "brisk", "broken", "bronze", "brown",
29 | "bruised", "bubbly", "bulky", "bumpy", "buoyant", "burdensome", "burly",
30 | "bustling", "busy", "buttery", "buzzing", "calculating", "calm", "candid",
31 | "canine", "capital", "carefree", "careful", "careless", "caring", "cautious",
32 | "cavernous", "celebrated", "charming", "cheap", "cheerful", "cheery", "chief",
33 | "chilly", "chubby", "circular", "classic", "clean", "clear", "clear-cut",
34 | "clever", "close", "closed", "cloudy", "clueless", "clumsy", "cluttered",
35 | "coarse", "cold", "colorful", "colorless", "colossal", "comfortable",
36 | "common", "compassionate", "competent", "complete", "complex", "complicated",
37 | "composed", "concerned", "concrete", "confused", "conscious", "considerate",
38 | "constant", "content", "conventional", "cooked", "cool", "cooperative",
39 | "coordinated", "corny", "corrupt", "costly", "courageous", "courteous",
40 | "crafty"
41 | ];
42 |
43 | let animals = [
44 | "aardvark", "african buffalo", "albatross", "alligator", "alpaca", "ant",
45 | "anteater", "antelope", "ape", "armadillo", "baboon", "badger", "barracuda",
46 | "bat", "bear", "beaver", "bee", "bison", "black panther", "blue jay", "boar",
47 | "butterfly", "camel", "capybara", "carduelis", "caribou", "cassowary", "cat",
48 | "caterpillar", "cattle", "chamois", "cheetah", "chicken", "chimpanzee",
49 | "chinchilla", "chough", "clam", "cobra", "cockroach", "cod", "cormorant",
50 | "coyote", "crab", "crane", "crocodile", "crow", "curlew", "deer", "dinosaur",
51 | "dog", "dolphin", "domestic pig", "donkey", "dotterel", "dove", "dragonfly",
52 | "duck", "dugong", "dunlin", "eagle", "echidna", "eel", "elephant seal",
53 | "elephant", "elk", "emu", "falcon", "ferret", "finch", "fish", "flamingo",
54 | "fly", "fox", "frog", "gaur", "gazelle", "gerbil", "giant panda", "giraffe",
55 | "gnat", "goat", "goldfish", "goose", "gorilla", "goshawk", "grasshopper",
56 | "grouse", "guanaco", "guinea fowl", "guinea pig", "gull", "hamster", "hare",
57 | "hawk", "hedgehog", "heron", "herring", "hippopotamus", "hornet", "horse",
58 | "human", "hummingbird", "hyena", "ibex", "ibis", "jackal", "jaguar", "jay",
59 | "jellyfish", "kangaroo", "kingfisher", "koala", "komodo dragon", "kookabura",
60 | "kouprey", "kudu", "lapwing", "lark", "lemur", "leopard", "lion", "llama",
61 | "lobster", "locust", "loris", "louse", "lyrebird", "magpie", "mallard",
62 | "manatee", "mandrill", "mantis", "marten", "meerkat", "mink", "mole",
63 | "mongoose", "monkey", "moose", "mosquito", "mouse", "mule", "narwhal", "newt",
64 | "nightingale", "octopus", "okapi", "opossum", "oryx", "ostrich", "otter",
65 | "owl", "oyster", "parrot", "partridge", "peafowl", "pelican", "penguin",
66 | "pheasant", "pigeon", "pinniped", "polar bear", "pony", "porcupine",
67 | "porpoise", "prairie dog", "quail", "quelea", "quetzal", "rabbit", "raccoon",
68 | "ram", "rat", "raven", "red deer", "red panda", "reindeer", "rhinoceros",
69 | "rook", "salamander", "salmon", "sand dollar", "sandpiper", "sardine",
70 | "scorpion", "sea lion", "sea urchin", "seahorse", "shark", "sheep", "shrew",
71 | "skunk", "snail", "snake", "sparrow", "spider", "spoonbill", "squid",
72 | "wallaby", "wildebeest"
73 | ];
74 |
75 | let keys = [];
76 |
77 | for animal in animals {
78 | for adjective in adjectives {
79 | for adverb in adverbs {
80 | keys.push(`${adverb} ${adjective} ${animal}`)
81 | }
82 | }
83 | }
84 |
85 | let map = #{};
86 |
87 | let i = 0;
88 |
89 | for key in keys {
90 | map[key] = i;
91 | i += 1;
92 | }
93 |
94 | let sum = 0;
95 |
96 | for key in keys {
97 | sum += map[key];
98 | }
99 |
100 | for key in keys {
101 | map.remove(key);
102 | }
103 |
104 | print(`Sum = ${sum}`);
105 | print(`Finished. Run time = ${now.elapsed} seconds.`);
106 |
--------------------------------------------------------------------------------
/test/switch.rhai:
--------------------------------------------------------------------------------
1 | // This script runs a switch statement in a for-loop.
2 |
3 | let arr = [42, 123.456, "hello", true, "hey", 'x', 999, 1, 2, 3, 4];
4 |
5 | for item in arr {
6 | switch item {
7 | // Match single character
8 | 'f' => |a, b| a !in b,
9 | // Match single integer
10 | 42 => print("The Answer!"),
11 | // Match a selection
12 | 1 | 2 | () | 3 | 4 => print("One two three four!"),
13 | // Match single floating-point number
14 | 123.456 => print(`Floating point... ${item}`),
15 | // Match single string
16 | "hello" => print(`${item} world!`),
17 | // Match another integer
18 | 999 => print(`Got 999: ${item}`),
19 | // Match range with condition
20 | 0..100 if item % 2 == 0 => print(`A small even number: ${item}`),
21 | // Match another range
22 | 0..100 => print(`A small odd number: ${item}`),
23 | // Default case
24 | _ => print(`Something else: <${item}> is ${type_of(item)}`)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/test/while.rhai:
--------------------------------------------------------------------------------
1 | // This script runs a while loop.
2 |
3 | let x = 10;
4 |
5 | while x > 0 {
6 | print(x);
7 | x -= 1;
8 | }
9 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": [
3 | "extension"
4 | ],
5 | "compilerOptions": {
6 | "outDir": "dist",
7 | /* Basic Options */
8 | "target": "ES5",
9 | "module": "commonjs",
10 | "lib": ["esnext", "dom"], /* Specify library files to be included in the compilation. */
11 | // "allowJs": true, /* Allow javascript files to be compiled. */
12 | // "checkJs": true, /* Report errors in .js files. */
13 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
14 | "declaration": true, /* Generates corresponding '.d.ts' file. */
15 | "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
16 | "sourceMap": true, /* Generates corresponding '.map' file. */
17 | // "outFile": "./", /* Concatenate and emit output to single file. */
18 | // "outDir": "./", /* Redirect output structure to the directory. */
19 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
20 | // "composite": true, /* Enable project compilation */
21 | "removeComments": true, /* Do not emit comments to output. */
22 | // "noEmit": true, /* Do not emit outputs. */
23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26 |
27 | /* Strict Type-Checking Options */
28 | "strict": true, /* Enable all strict type-checking options. */
29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
30 | // "strictNullChecks": true, /* Enable strict null checks. */
31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */
32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
35 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
36 |
37 | /* Additional Checks */
38 | // "noUnusedLocals": true, /* Report errors on unused locals. */
39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
42 |
43 | /* Module Resolution Options */
44 | //"resolveJsonModule": true, /* Import json as object. */
45 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
46 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
47 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
48 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
49 | // "typeRoots": [], /* List of folders to include type definitions from. */
50 | // "types": [], /* Type declaration files to be included in compilation. */
51 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
52 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
53 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
54 |
55 | /* Source Map Options */
56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
60 |
61 | /* Experimental Options */
62 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
63 | "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
64 | },
65 | "compileOnSave": true,
66 | }
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "semicolon": [
4 | true,
5 | "never"
6 | ],
7 | "quotemark": [
8 | true,
9 | "single",
10 | "avoid-escape",
11 | "avoid-template"
12 | ],
13 | "indent": [
14 | true,
15 | "spaces",
16 | 4
17 | ],
18 | "object-literal-key-quotes": [
19 | true,
20 | "consistent-as-needed"
21 | ],
22 | "no-var-requires": true,
23 | "member-access": false,
24 | "trailing-comma": [
25 | true,
26 | {
27 | "multiline": "always",
28 | "singleline": "never"
29 | }
30 | ]
31 | },
32 | "linterOptions": {
33 | "exclude": [
34 | "dist/**",
35 | "node_modules/**",
36 | "*.d.ts"
37 | ]
38 | }
39 | }
--------------------------------------------------------------------------------